您的位置:首页 > 其它

HDU 2600 War

2015-11-07 21:17 423 查看
HDU 2600 
War
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2600
题目大意:

给出一个初始区间和n个覆盖区间。
如果所有的覆盖区间不能全部覆盖初始区间,则输出区间上没有被覆盖的最大的点。
如果初始区间被完全覆盖,则输出 “Badly!”。
 

典型的贪心,区间覆盖四个字都写到脸上了。

对于所有的覆盖区间[Ai,Bi],首先要进行排序,然后才能进行下一步操作。那么排序时要按照哪个部分进行呢? 按照计算开始的顺序,如果从起始点开始,就按照左端点排序。如果从终点开始,就按照右端点排序。

我比较喜欢顺其自然,接下来的讨论只针对从起始点开始的情况。

当所有覆盖区间排序完毕,接下来我们就要思考:如何获得未被覆盖的区间最大值。

这里提供一种思路,首先,我们要判断起始区间是否被完全覆盖。

因为覆盖区间都按照起始点进行排序,那么我们只需要进行覆盖计算,就能知道覆盖区域大小。

 

那么就分为这么几种情况:

因为只讨论最大的未被覆盖值,所以我们只看最后面的点。

1. 起始区间未被完全覆盖,尾端未被完全覆盖。

 


2. 起始区间未被完全覆盖,两端被覆盖,中间某处未被覆盖。

 


3. 起始区间未被完全覆盖,起始端未被完全覆盖。

 


4. 起始区间完全被覆盖。

这种情况直接可以输出 “Badly!”了。

有上面可得,我们需要同时计算两个点:最大的覆盖区间的左端点之后的点Pl,右端点之前的点Pr。然后就可以得出结果,伪代码如下:

初始化 Pl = 第一个覆盖区间的左端点 - 1;

初始化 Pr = 第一个覆盖区间的右端点 + 1;

<span style="font-family:Microsoft YaHei;">for( 针对每个覆盖区间 )
{
if ( 该覆盖区间不和上一个重合 )
{
更新Pl的值
}
if( 该端点的右端点比pr大 )
{
更新Pr的值
}
}
if( Pr 小于等于 初始区间的最右端点 )
{
输出Pr。
}else if( Pl 大于等于 初始区间的最左端点 )
{
输出Pl。
}else
{
输出 “Badly!”
}</span>


ac代码:

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

#define NUM 105

#define INF 0XFFFFFFFF

struct Node
{
int start;
int end;
};

int cmp(Node a,Node b)
{
if(a.start != b.start){
return a.start < b.start;
}

return a.end > b.end;
}

Node map;
Node arr[NUM];

int main()
{
int N = 0;
while(cin>>N){
cin>>map.start>>map.end;

char name_tmp[1024];
for(int i = 1; i <= N; i++){
cin>>arr[i].start>>arr[i].end;
cin.getline(name_tmp, 1024);
}

sort(arr+1, arr+N+1, cmp);

int pos_min = -INF;
if(arr[1].start > map.start){
pos_min = arr[1].start -1;
}
int pos_max = arr[1].end;

for(int i = 2; i <= N; i++){
if(arr[i].start > arr[i-1].end + 1){///´æÔÚδ¸²¸ÇµÄ¿Õ¼ä
pos_min = arr[i].start -1;
}

if(arr[i].end > pos_max){
pos_max = arr[i].end;
}
}

if(pos_max < map.end){
cout<<map.end<<endl;
}else if(pos_min != -INF){
cout<<pos_min<<endl;
}else{
cout<<"Badly!"<<endl;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: