原题地址:点击打开链接
题意:
给定N个小区间[Si, Ei],求能用它们覆盖区间[1,T]的最小组合。
数据范围:
1 <= N <= 25000
1 <= T <= 10^6
输入:
第一行: N T
第2到第N+1行: 区间起点Si 区间终点Ei
输出:
一行:最少区间数,如果不能覆盖输出-1
例子:
输入:
3 10
1 7
3 6
6 10
输出:
2
这个题我自己没做出来,不知道为什么总是Wrong Answer,日后回头再看,暂且传上大神的思路和代码:(原文传送地址:点击打开链接)
贪心策略是从左往右,尽量选择长度最大的区间。
首先对所有奶牛排序,按照开始时间排序。
然后更新起点=终点+1,搜索剩下的奶牛中能够覆盖这个起点同时终点最远的那一头,更新终点。
#include <iostream>
#include <algorithm>
using namespace std;
int N, T;
struct Cow
{
int begin; // 开始时间
int end; // 结束时间
};
#define MAX_COWS 25000
Cow cow[MAX_COWS];
bool is_greater(const Cow& a, const Cow& b)
{
return a.begin < b.begin || (a.begin == b.begin && a.end > b.end);
}
int solve()
{
int used_cows = 0;
int end = 0;
int index = 0;
while(end < T)
{
int begin = end + 1;
// 寻找一头既能从begin干起,又能一直干到最远的牛
for (int i = index; i < N; ++i)
{
if (cow[i].begin <= begin)
{
// 能够覆盖起始点
if (cow[i].end >= begin)
{
// 将终点延长到最远
end = max(end, cow[i].end);
}
}
else
{
// 不能覆盖起始点,说明上一头牛的终点就是最远点,需要换一头牛了
index = i;
break;
}
}
// 没找到这样的牛,这个case失败
if (begin > end)
{
return -1;
}
else
{
++used_cows;
}
}
return used_cows;
}
///SubMain//
int main(int argc, char *argv[])
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
cin >> N >> T;
for (int i = 0; i < N; ++i)
{
cin >> cow[i].begin >> cow[i].end;
}
sort(cow, cow + N, is_greater);
cout << solve() << endl;
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
system("out.txt");
#endif
return 0;
}
///End Sub//
我的代码(提交Wrong Answer):
#include <iostream>
#include <algorithm>
#define MAX_N 25000
using namespace std;
int N, T;
//保存N个区间,并用于排序
pair<int, int> itv[MAX_N];
//排序的比较
bool compare(const pair<int, int> &a, const pair<int, int> &b)
{
if(a.first == b.first)
return a.second < b.second;
return a.first < b.first;
}
void solve()
{
//按区间起点排序
sort(itv, itv + N, compare);
int ans = 0;
int end = 0; //当前覆盖的区间[1, end]
int i = 0;
while(end < T){
//查找可选区间中最右的
int t = end + 1;
while(i < N){
if(itv[i].first <= t){
if(itv[i].second >= t)
end = max(end, itv[i].second);
}
else
break;
i ++;
}
//找到了可选区间
if(end > t)
ans ++;
//找不到可选区间
else{
cout << "-1" << endl;
return;
}
}
cout << ans << endl;
}
int main()
{
while(cin >> N >> T){
for(int i = 0; i < N; i ++)
cin >> itv[i].first >> itv[i].second;
solve();
}
return 0;
}
不知道错在哪了,主要是测试数据太少了。。不过还是学到了一些东西,现在总结一下:
pair模板的使用:
定义:pair < type, type> name;
访问第一个元素: name.first, 访问第二个元素:name.second
排序:如果对pair类型排序,第一个元素的值优先
详细解释:点击打开链接
sort函数可以加第三个参数,用于比较方式:点击打开链接
最后最重要重要的:
贪心的核心思想:不断选取当前最优解,但解法需要自己证明是否正确,用贪心解决问题是非常高效的,麻烦的就是不知道自己的策略 是不是正确的。