最少区间覆盖问题,高分请教

hongyzniu 2009-04-09 09:25:13
问题描述:
给出一些区间[Li,Ri],请你找到这些区间的一个子集,使得子集里的区间完全覆盖[0,M].

关于输入
第一行包含一个数M(1<=M<=50000).
接下来每行包含一对数Li和Ri(|Li|<=50000,|Ri|<=50000),最后以"0 0"结束.

关于输出
输出一个整数,表示最少需要多少个区间覆盖[0,M],如果无解,则输出"No solution"

例子输入
1
-1 0
0 1
0 0


下面是我写的代码,但是提交说超时了,请各位帮忙看看....


/********************************************
队列求解问题
********************************************/
#include <iostream>
#include <queue>
using namespace std;


int main()
{
int M,temp;
cin>>M;
int l,r,right,maxright=0,Count=0,j=0; //Count用作区间数记数
queue<int>q1;
int q2; //记录队列的大小
while(cin>>l>>r && !(l==0 && r==0))
{
if(l<=0)
{
if(maxright<r)maxright=r;
}
else
{
q1.push(l);
q1.push(r); //先压右边,后压左边,每次取两元素
}
}

//以上为接受输入,下面每次都将队列中的元素按照maxright作为界限分成两组
//如果上面的答案中每有产生maxright>0,那么可以肯定必然无解
//如果上面的答案中产生的maxright是介于0-M之间的数,继续下面的操作
//如产生的答案中maxright>=M,可以肯定只要一个区间就可以完全覆盖。
if(maxright==0){cout<<"No solution\n";}
else if(maxright>=M){cout<<"1\n";}
//就是用一个队列来存储那些左边比当前右边大的组合,等到后面再继续处理...
else if(maxright>0 && maxright<M)
{
Count=2;
while(!q1.empty())
{
temp=maxright;
q2=q1.size();
while(j<q2)
{
if(q1.front()<=temp)
{
if(!q1.empty()){
q1.pop();
if(q1.front()>maxright){maxright=q1.front();}
q1.pop();
j+=2;}
}
else
{
if(!q1.empty()){
q1.push(q1.front());
q1.pop();
q1.push(q1.front());
q1.pop();
j=j+2;}
}
}
if(maxright==temp){cout<<"No solution\n";break;}
else if(maxright>=M){cout<<Count<<endl;break;}
else if(maxright<M && maxright>temp)
{
Count++;j=0;
}
}
}

return 0;
}


...全文
898 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
wwwypy 2009-04-13
  • 打赏
  • 举报
回复
应该是那个学校的ACM把,我在编程之美中看到过差不多的题,楼主有时间看看。
liliangbao 2009-04-10
  • 打赏
  • 举报
回复
帮顶~
feng4206yu 2009-04-09
  • 打赏
  • 举报
回复
提出一点输入时的改动意见:
1.当区间左值<=0时,将其区间右值与maxright比较后就可放弃,这种区间可以不用放入队列...
2.当区间左值>M时,这种区间也可以不用放入队列...
ltc_mouse 2009-04-09
  • 打赏
  • 举报
回复
给一个测试例,每个区间的长度为1,[0,1],[1,2],...[k,k+1],...
当M=5000时,你的程序在我机器上需要20秒以上了...

测试时,将输入语句调整成自动生成子区间,如下:

//while(cin>>l>>r && !(l==0 && r==0))
for(l=0,r=1; r<=M; l++,r++)
feng4206yu 2009-04-09
  • 打赏
  • 举报
回复
看了一下,思路应该是没有太大的问题...
1.M不一定是整数...但是他的例子输入里倒是全是整数...
2.不知道超时是怎么回事...所以不知道小改动倒底有没有什么实质的效果

/********************************************
最小区间覆盖问题
********************************************/
#include <iostream>
#include <queue>
using namespace std;


int main()
{
int M,temp;
cin>>M;
int l,r,maxright=0,Count=0,j=0; //Count用作区间数记数
//所有区间最大右值
int maxofall = 0;
queue<int>q1;
int q2; //记录队列的大小
while(cin>>l>>r && !(l==0 && r==0))
{
if(l<=0)
{
if(maxright<r) maxright=r;
}
else
{
q1.push(l);
q1.push(r); //先压左边,后压右边,每次取两元素
}
if(maxofall<r) maxofall=r;
}

//以上为接受输入,下面每次都将队列中的元素按照maxright作为界限分成两组
//如果上面的答案中没有有产生maxright>0,那么可以肯定必然无解
//如果上面的答案中产生的maxright是介于0-M之间的数,继续下面的操作
//如产生的答案中maxright>=M,可以肯定只要一个区间就可以完全覆盖。
if(maxright==0 || maxofall < M){cout<<"No solution\n";}
else if(maxright>=M){cout<<"1\n";}
//就是用一个队列来存储那些左边比当前maxright大的组合,等到后面再继续处理...
else if(maxright>0 && maxright<M)
{
Count=2;
while(!q1.empty())
{
temp=maxright;
q2=q1.size();
while(j<q2)
{
//左值小于等于0的区间没有用处,这一步只会运行一次...
if(q1.front()<=0)
{
if(!q1.empty()){
q1.pop();
q1.pop();
j+=2;}
}
//左值大于M的区间没有用处,这一步只会运行一次....
else if(q1.front()>M)
{
if(!q1.empty()){
q1.pop();
q1.pop();
j+=2;}
}
//左值大于0但小于等于temp的区间
else if(q1.front()<=temp)
{
if(!q1.empty()){
q1.pop();
if(q1.front()>maxright){maxright=q1.front();}
q1.pop();
j+=2;}
}
//左值大于temp但小于M的区间
else
{
if(!q1.empty()){
q1.push(q1.front());
q1.pop();
q1.push(q1.front());
q1.pop();
j=j+2;}
}
}
if(maxright==temp){cout<<"No solution\n";break;}
else if(maxright>=M){cout<<Count<<endl;break;}
else if(maxright<M && maxright>temp)
{
Count++;j=0;
}
}
}

return 0;
}

有什么可讨论的可以继续...
hongyzniu 2009-04-09
  • 打赏
  • 举报
回复
顶上去.....
woods2001 2009-04-09
  • 打赏
  • 举报
回复
看看~
hongyzniu 2009-04-09
  • 打赏
  • 举报
回复
注释有部分错误...
程序改了 注释没改...晕

64,648

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧