複習時食用,會比較簡略。
目錄
#10000. 「一本通 1.1 例 1」活動安排
題目大意
有n個活動,每個活動i都有起始時間s_i和結束時間f_i。
若區間[s_i,f_i)與區間[s_j,f_j)不相交,則活動i與活動j相容。
選擇出由互相兼容的活動組成的最大集合。
1<=n<=1000。
題目分析
貪心。
將每個活動的結束時間從小到大排序。
每次選擇結束時間最早的且開始時間大於等於結束時間的活動。
代碼
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{int s,f;}a[1010];
int cmp(node x,node y)
{
if(x.f==y.f) return x.s<y.s;
else return x.f<y.f;
}
int main()
{
int n; scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].s,&a[i].f);
sort(a+1,a+1+n,cmp);//按結束時間從小到大排序
int ans=1,end=a[1].f-1;
for(int i=2;i<=n;i++)
{
if(a[i].s>end) { ans++; end=a[i].f-1; }
}
printf("%d",ans);
return 0;
}
#10001. 「一本通 1.1 例 2」種樹
題目大意
某條街被劃爲n條路段,每個路段可以種一棵樹。
給出了h組建議,希望在路段b到e之間至少要種t棵樹。
問至少要種多少棵樹。
30%的數據滿足0<n<=1000,0<h<=500;
100%的數據滿足0<n<3*10^4,h<=5000,0<b<=e<=3*10^4,t<=e-b+1。
題目分析
貪心。
跟上一題有異曲同工之妙。
代碼
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
bool b[30010];
struct node{int b,e,t;}a[5010];
int cmp(node x,node y) { return x.e<y.e; }
int main()
{
int n,h; scanf("%d%d",&n,&h);
memset(b,false,sizeof(b));
for(int i=1;i<=h;i++)
{
scanf("%d%d%d",&a[i].b,&a[i].e,&a[i].t);
}
sort(a+1,a+1+h,cmp);//按種樹路段的末尾排序
int ans=0;
for(int i=1;i<=h;i++)
{
int s=0;//先找這一段路已有的樹
for(int j=a[i].b;j<=a[i].e;j++) if(b[j]) s++;
if(s<a[i].t)//還沒有種夠
{
for(int j=a[i].e;j>=a[i].b;j--)
{
if(b[j]==false)//這個位置沒有樹就種啊
{
s++; b[j]=true; ans++;
if(s==a[i].t) break;
}
}
}
}
printf("%d",ans);
return 0;
}
#10002. 「一本通 1.1 例 3」噴水裝置
題目大意
長L米,寬W米的草坪裏裝有n個澆灌噴頭。
每個噴頭都裝在草坪中心線上。
知道每個噴頭的位置,以及它能覆蓋到的澆灌範圍。
問同時澆灌整塊草坪最少需要打開多少個噴頭?
對於100%的數據,n<=15000。
題目分析
. . “.” . .
. “.” .
“.”
. “.” .
. . “.” . .
帶下劃線的爲半徑,“引號”中的是草坪寬。
紅色的是能澆灌到的最邊上的草坪寬,用kk=sqrt(r*r-(w/2)*(w/2))表示。是美妙的勾股啊!!
則最左邊a[s].a=x-kk,最右邊a[s].b=x+kk。
如果澆灌的半徑*2<草坪寬就不考慮這個噴頭,不要問我爲什麼,或者你告訴我要它有何用。
剩下的水到渠成。
還不懂就看代碼吧。
代碼
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
struct node{double a,b;}a[15010];
int cmp(node x,node y) { return x.a<y.a; }
int main()
{
int t; scanf("%d",&t);
while(t--)
{
int n,l,w,s=0; scanf("%d%d%d",&n,&l,&w);
for(int i=1;i<=n;i++)
{
int x,y; scanf("%d%d",&x,&y);
if(y*2<w) continue; s++;
double kk=sqrt(y*y*1.0-w*w/4.0);
a[s].a=x*1.0-kk;//能澆灌到的最邊上的最左
a[s].b=x*1.0+kk;//能澆灌到的最邊上的最右
}
sort(a+1,a+1+s,cmp);
int d=1,ans=0;
double ll=0;//目前能澆灌到的最邊上的草坪的長
bool k=true;
while(ll<l)//革命尚未成功
{
ans++; double maxx=ll;
while(a[d].a<=maxx&&d<=s)
{
ll=max(ll,a[d].b); d++;
//當然是找符合要求且半徑長的噴頭a
}
if(maxx==ll) { printf("-1\n"); k=false; break; }
}
if(k) printf("%d\n",ans);
}
return 0;
}
#10003. 「一本通 1.1 例 4」加工生產調度
題目大意
n個產品在A、B兩個車間加工,必須先在A車間加工後纔可以到B車間加工。
產品i在A,B兩車間加工的時間分別爲 A_i, B_i,安排這 n個產品的加工順序,使總的加工時間最短。
對於100%的數據,0<n<1000,所有數值皆爲整數。
題目分析
???沒有分析,很迷???
一本通上的證明並沒有看懂,我太辣雞了。
反正是這樣做的:
設Mi=min(ai,bi)。
將M從小到大排序,若Mi=ai,就將它放在從頭開始的作業後面。
反之放在從尾開始的作業前面。
順序排好了就直接做啊。
代碼
#include<cstdio>
#include<cstring>
#include<cstring>
#include<algorithm>
using namespace std;
int s[1010];
struct nod1{int a,b,m,h;}a[1010];
struct nod2{int a,b;}b[1010];
int cmp(nod1 x,nod1 y) { return x.m<y.m; }
int main()
{
int n; scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i].a);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].b);
a[i].m=min(a[i].a,a[i].b); a[i].h=i;
b[i].a=a[i].a; b[i].b=a[i].b;
}
sort(a+1,a+1+n,cmp);
int st=1,ed=n;
for(int i=1;i<=n;i++)
{
if(a[i].m==a[i].a) { s[st]=a[i].h; st++; }
else { s[ed]=a[i].h; ed--; }
}
int ans=0,d=0;
for(int i=1;i<=n;i++)
{
d+=b[s[i]].a;
ans=max(d+b[s[i]].b,ans+b[s[i]].b);
}
printf("%d\n",ans);
for(int i=1;i<=n;i++) printf("%d ",s[i]);
return 0;
}
#10004. 「一本通 1.1 例 5」智力大沖浪
題目大意
比賽分爲n個時段,每個遊戲都必須在t_i前完成,否則從獎勵費m元中扣去一部分錢 w_i。
每個遊戲能在一個時段內完成,問小偉能贏取最多的錢。
對於100%的數據,有n<=500,1<=t_i<=n。
題目分析
肯定挑錢多的先做啊,需要爲什麼嗎???
代碼
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
bool f[250010];
struct node{int time,money;}a[510];
int cmp(node x,node y) { return x.money>y.money; }
int main()
{
int m,n; scanf("%d%d",&m,&n);
memset(f,false,sizeof(f));
for(int i=1;i<=n;i++) scanf("%d",&a[i].time);
for(int i=1;i<=n;i++) scanf("%d",&a[i].money);
sort(a+1,a+1+n,cmp);//按錢的多少排序
for(int i=1;i<=n;i++)
{
bool k=false;
for(int j=a[i].time;j>=1;j--)
{
if(!f[j]) { f[j]=true; k=true; }
if(k) break;
}
if(!k) m-=a[i].money;
}
printf("%d",m);
return 0;
}