家庭作业(信息学奥赛一本通 1430)
【题目描述】
老师在开学第一天就把所有作业都布置了,每个作业如果在规定的时间内交上来的话才有学分。每个作业的截止日期和学分可能是不同的。例如如果一个作业学分为10,要求在6天内交,那么要想拿到这10学分,就必须在第6天结束前交。
每个作业的完成时间都是只有一天。例如,假设有7次作业的学分和完成时间如下:
作业号 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
期限 |
1 |
1 |
3 |
3 |
2 |
2 |
6 |
学分 |
6 |
7 |
2 |
1 |
4 |
5 |
1 |
最多可以获得15学分,其中一个完成作业的次序为2,6,3,1,7,5,4,注意可能d还有其他方法。
你的任务就是找到一个完成作业的顺序获得最大学分。
【输入】
第一行一个整数N,表示作业的数量。
接下来N行,每行包括两个整数,第一个整数表示作业的完成期限,第二个数表示该作业的学分。
【输出】
输出一个整数表示可以获得的最大学分。保证答案不超过longint范围。
【输入样例】
7 1 6 1 7 3 2 3 1 2 4 2 5 6 1
【输出样例】
15
这道题和ybt上的1426 智力大冲浪 比较相像,一开始我就是直接用1426的代码做的,上代码——
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n; 4 int k,m,p,w,ans,l,s; 5 bool u[1000001]; 6 struct node{ 7 int a,b; 8 bool operator <(const node &y)const 9 { 10 return b>y.b; 11 } 12 }x[1000001]; 13 int read() 14 { 15 int f=1;char ch; 16 while((ch=getchar())<'0'||ch>'9') 17 if(ch=='-')f=-1; 18 int res=ch-'0'; 19 while((ch=getchar())>='0'&&ch<='9') 20 res=res*10+ch-'0'; 21 return res*f; 22 } 23 void write(int x) 24 { 25 if(x<0) 26 { 27 putchar('-'); 28 x=-x; 29 } 30 if(x>9)write(x/10); 31 putchar(x%10+'0'); 32 } 33 int main() 34 { 35 n=read(); 36 for(int i=1;i<=n;i++) 37 { 38 x[i].a=read(),x[i].b=read(); 39 s+=x[i].b; 40 } 41 sort(x+1,x+1+n); 42 for(int i=1;i<=n;i++) 43 { 44 int flag=0; 45 for(int j=x[i].a;j>=1;j--) 46 if(!u[j]) 47 { 48 u[j]=true; 49 flag=1; 50 break; 51 } 52 if(!flag) 53 { 54 for(int j=n;j>=1;j--) 55 if(!u[j]) 56 { 57 u[j]=1; 58 break; 59 } 60 s-=x[i].b; 61 } 62 } 63 write(s); 64 return 0; 65 }
然鹅只有可伶的50分,有五个点都TLE了┭┮﹏┭┮
所以说这道题肯定就没有这么简单啦(虽然说本来就是很简单的水题
那么我们进一步优化吧,,,
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 struct homework 6 { 7 int k,date; 8 }a[1000001]; 9 int read() 10 { 11 char ch=getchar(); 12 int a=0,x=1; 13 while(ch<'0'||ch>'9') 14 { 15 if(ch=='-') x=-x; 16 ch=getchar(); 17 } 18 while(ch>='0'&&ch<='9') 19 { 20 a=(a<<3)+(a<<1)+(ch-'0'); 21 ch=getchar(); 22 } 23 return a*x; 24 } 25 int cmp(homework x,homework y) //按照学分从大到小排序 26 { 27 return x.k>y.k; 28 } 29 int n,sum,q,hash[1000001]; 30 int pan(int x) 31 { 32 for(int i=a[x].date;i>=1;i--) 33 { 34 if(hash[i]==0) 35 { 36 hash[i]=1; 37 return 1; 38 } 39 } 40 q=a[x].date; //如果到了这里,说明1~a[x].date已经安排满了,用q记录下来 41 return 0; 42 } 43 int main() 44 { 45 n=read(); 46 for(int i=1;i<=n;i++) 47 { 48 a[i].date=read(); 49 a[i].k=read(); 50 } 51 sort(a+1,a+1+n,cmp); 52 for(int i=1;i<=n;i++) 53 { 54 if(a[i].date<q) continue; //直接跳出,节省时间 55 if(pan(i)) sum+=a[i].k; 56 } 57 printf("%d\n",sum); 58 return 0; 59 }