タイトル:間隔カバレッジ
質問の意味:Nはい(1 <= N <= 25000) 閉区間、いくつかのセクションでは、指定されたラインセグメントを覆うよう、BI aiを】数ラインは、選択し[1、T](1 < = T <= 1,000,000)。
全体のポイントをカバーする、即ち、(1,2)+(3,4)(1,4)を覆うことができます。
不可能を出力-1
入力:
最初のライン:N Tと
第二行N + 1行に各ライン閉区間。
出力:
選択したセクションの数、不可能出力-1
問題解決のアイデア:インターバルカバレッジの問題貪欲解決;尾に行く頭、ある、行の左端が1に彼をできるように1つの未満の点である(右の終点が1未満であれば、影響はありません)、その行を昇順にソートポイントを残しました。そして、右の時間が特別審査員を行うために、左の点と異なる場合、(その後、左の点の場合と同じ)の最大のポイントを取るために、次の点を見てみるならば、(プラスワンは、上記のヒントを持っている必要があります)+1の値に残されていません場合は、停止出力に-1;いない場合、ポイントはあなたの現在選択されている線分の右端ポイントに左エンドラインを上書きして、結果が得られまで、頭を切断していきたい。
このメソッドは、なぜそれができますか?私たちは、最大のものを左のポイントは以下で値が1行目の右端のポイントである、たとえば、我々が選択した、カバーほとんどのセグメントを左マイナス1;あなたはこれを選択しない場合は、その後、我々は、これより小さいものを選ぶことができますあなたはより多くの範囲の残りの部分よりも、あなたの状況は良くも、悪くなっていないとなると、またはあなたが一番左の選択が完了した後、同じに直面して、この行の問題を継続することを選択しました。ここから私たちは、貪欲が最適であることを見ることができます。
類似のトピック(邪悪な牛)
欺瞞場所:ください、ノート、上記のことを全体のポイントをカバーする、それが来るとき、私は、彼らは線分覆い、白に続いクレイジーだと思った、この情報はありません。。。だから、1を追加してください!
コード:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
using namespace std;
bool cmp(pair<int,int> a,pair<int,int> b)
{
return a.first<b.first;
}
int main()
{
int n,t,x,y;
vector<pair<int,int> > h;
while(scanf("%d%d",&n,&t)!=EOF)
{
int total=1,flag=-1,b=1;
for(int i=0;i<n;i++)
{
scanf("%d%d",&x,&y);
if(x>y)//由于被坑的有点厉害,就谨慎了一点
{
swap(x,y);
}
if(x<1){x=1;}//裁剪
if(y>t){y=t;}
h.push_back(make_pair(x,y));
}
if(n==0||t<1)//谨慎
{
printf("-1\n");
h.clear();
continue;
}
sort(h.begin(),h.end(),cmp);//排序
if(h[0].first>1)//特判第一个
{
printf("-1\n");
h.clear();
continue;
}
for(int i=0;i<n;i++)//进行贪心
{
if(h[i].first>b)//如果当前线段左端点数值和b不同,说明左端点为b的线段已经筛选完了
{
if(h[i].first>flag+1)//记住,一定要加个1!!!
{
printf("-1\n");
break;
}
total++;//所选的线段数加1
for(int j=i;j<n;j++)//把左端点进行变更,并进行裁剪
{
if(h[j].first<flag+1)
{
h[j].first=flag+1;
}else
{
break;
}
}
b=flag+1;//变更左端点
}
flag=max(flag,h[i].second);//求个右端点最大的
if(flag==t)//判断一下
{
printf("%d\n",total);
break;
}
if(i==n-1)//扫完了还没成功,就说明失败了
{
printf("-1\n");
}
}
h.clear();
}
}