hdu 1799 Doing Homework again

来源:互联网 发布:华测rtk如何导出数据 编辑:程序博客网 时间:2024/05/17 20:10
Problem Description
Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. 
Every teacher gives him a deadline of handing in the homework.If Ignatius hands in the homework after the deadline, 
the teacher will reduce his score of the final test. And now we assume that doing everyone homework always takes one day. 
So Ignatius wants you to help him to arrange the order of doing homework to minimize the reduced score.

Input:
The input contains several test cases. The first line of the input is a single integer T that is the number of test cases. T test cases follow.
Each test case start with a positive integer N(1<=N<=1000) which indicate the number of homework.. Then 2 lines follow. The first line contains N integers that indicate the deadlines of the subjects, and the next line contains N integers that indicate the reduced scores.
Output:
For each test case, you should output the smallest total reduced score, one line per test case.

Sample Input
333 3 310 5 131 3 16 2 371 4 6 4 2 4 33 2 1 7 6 5 4
Sample Output
035
!!详细注解在最后。。。。
错误思路:
从第一天到最后一天,先安排多个同一天的中的最大值,安排在对应的那天中,再用没安排的比较安排的的,如果有满足条件并罚天数较大,
就代替掉原来安排的。
#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>using namespace std;struct f{ int deadline,score;}a[1100],c[1100];int book[1100];bool cmp(f p,f q){  if(p.deadline==q.deadline) return p.score>q.score;//时间排序基础上,罚分从大到小排序 return p.deadline<q.deadline;//截至时间从小到大排 }int b[1100];int main(){ int t;cin>>t; while(t--){      int n,s=0;     memset(book,0,sizeof(book));     memset(b,0,sizeof(b));     memset(a,0,sizeof(a));     memset(c,0,sizeof(c));      cin>>n;      for(int i=1;i<=n;i++)  cin>>a[i].deadline;      for(int i=1;i<=n;i++){scanf("%d",&a[i].score);s+=a[i].score;}       sort(a+1,a+n+1,cmp);       int k=0;       for(int i=1;i<=n;i++)       {           if(b[a[i].deadline]==0) b[a[i].deadline]=a[i].score;//先安排好同一天中的(最大罚分)的那个           else {             c[++k].deadline=a[i].deadline;             c[k].score=a[i].score;           }       }       int sum=0;       for(int i=1;i<=1000;i++){            int maxn=b[i]/*原来安排的值*/,p=0;          for(int j=1;j<=k;j++)         {             if(!book[j]&&c[j].deadline>=i&&c[j].score>maxn){maxn=c[j].score;p=j;}         }         if(p!=0) book[p]=1;         sum+=maxn;//一轮比较可能就将原来的值代替掉了  (bug:代替掉就不管了,有可能它可以代替前面(截至天数比它小的)而得到更优的解。       }       cout<<s-sum<<endl; }return 0;}
//自己思路下,繁琐写了下#include<cstdio>#include<cstring>#include<algorithm>using namespace std;struct f{    int deadline,score;}a[1500];int book[1500];int yy[1500]; //**int no[1500]; //**int bookno[1500]; //**bool cmp(f p,f q){   if(p.deadline==q.deadline) return p.score>q.score;  return p.deadline<q.deadline;}bool cmp1(int x,int y){ //**只为维护sum值    if(a[x].score==a[y].score) return a[x].deadline>a[y].deadline; return a[x].score>a[y].score;}int main(){    int t;    scanf("%d",&t);    while(t--){        memset(yy,0,sizeof(yy));        memset(book,0,sizeof(book));        memset(bookno,0,sizeof(bookno));    int n,s=0;    scanf("%d",&n);    for(int i=1;i<=n;i++)  scanf("%d",&a[i].deadline);    for(int i=1;i<=n;i++){scanf("%d",&a[i].score);s+=a[i].score;}     sort(a+1,a+n+1,cmp);     int sum=0;    for(int i=1;i<=n;i++)    {        if(book[i]) continue;        if(a[i].deadline!=i){          int maxn=0,p=0;        for(int j=i;j<=n;j++)        {            if(!book[j]&&a[j].deadline>i&&a[j].score>maxn) {maxn=a[j].score;p=j;}        }         book[p]=1;sum+=a[p].score;yy[i]=p;           }        else {sum+=a[i].score;yy[i]=i;book[i]=1;}    }    int k=0;    for(int i=1;i<=n;i++)     if(!book[i]) no[k++]=i;     sort(no,no+k,cmp1);    for(int i=1;i<=n;i++)    {        if(yy[i]==0) break;        else{        for(int j=0;j<k;j++)        {                if(!bookno[j]&&a[no[j]].deadline>a[yy[i]].deadline&&a[no[j]].score>a[yy[i]].score)                {                       bookno[j]=1;sum+=a[no[j]].score-a[yy[i]].score;                       break;                }        }        }    }    printf("%d\n",s-sum);}return 0;}
//思路下,,二维数组写了下#include<cstdio>#include<cstring>#include<algorithm>using namespace std;struct f{ int deadline,score;}a[1100];bool cmp1(int x,int y){return x>y;}int num[1100][1100];int book[1100][1100];int main(){    int t;    scanf("%d",&t);    while(t--){            memset(num,0,sizeof(num));            memset(book,0,sizeof(book));            int n,s=0;        scanf("%d",&n);       for(int i=1;i<=n;i++)  scanf("%d",&a[i].deadline);       for(int i=1;i<=n;i++){scanf("%d",&a[i].score);s+=a[i].score;}       int k=0;      for(int i=1;i<=n;i++)      {          num[a[i].deadline][k++]=a[i].score;      }      for(int i=1;i<=n;i++)       sort(num[i],num[i]+1005,cmp1);       int sum=0;        for(int i=1;i<=n;i++)       {          int maxn=num[i][0],p=i,q=0;         for(int j=i+1;j<=n;j++)         {            for(int l=1;num[j][l]!=0;l++)             {                 if(!book[j][l]&&num[j][l]>maxn){maxn=num[j][l];p=j;q=l;break;}             }         }         book[p][q]=1;  sum+=maxn;       }       printf("%d\n",s-sum);    }return 0;}//ps:写法试了不少但思路wrong
得到正确思路:按截至时间从后向前,每次取截至时间(包括本身)之后的罚分数最大的就可得到最优解
#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>using namespace std;struct f{ int deadline,score;}a[1100];int book[1100];bool cmp(f p,f q){  if(p.deadline==q.deadline) return p.score<q.score; return p.deadline<q.deadline; }int main(){ int t;cin>>t; while(t--){      int n,s=0;      memset(book,0,sizeof(book));      cin>>n;      for(int i=1;i<=n;i++)  cin>>a[i].deadline;      for(int i=1;i<=n;i++){scanf("%d",&a[i].score);s+=a[i].score;}       sort(a+1,a+n+1,cmp);      // for(int i=1;i<=n;i++)       // printf("=%d %d\n",a[i].deadline,a[i].score);        int sum=0;       for(int i=n;i>=1;i--)       {              int maxn=0,p=0;            for(int j=i;j<=n;j++)              if(!book[j]&&a[j].deadline>=i&&a[j].score>maxn){                  maxn=a[j].score;p=j;//printf("i=%d j=%d p=%d\n",i,j,p);              }             sum+=maxn;book[p]=1;       }       cout<<s-sum<<endl; }return 0;}//ac
//写了一篇总结,准备发呢,才意识到两天前刚写过0_0',这次清楚多了,时间是枚解药呀。这就是上面ac代码的注解和小修改。#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>using namespace std;struct f{ int deadline,score;}a[1100];int book[1100];bool cmp(f p,f q){ return p.deadline<q.deadline; //按时间从小到大排序(0_0) }  int main(){ int t;cin>>t; while(t--){      int n,s=0;      memset(book,0,sizeof(book));      cin>>n;      for(int i=1;i<=n;i++)  cin>>a[i].deadline;      for(int i=1;i<=n;i++){scanf("%d",&a[i].score);s+=a[i].score;}       sort(a+1,a+n+1,cmp);       /*排序后可假设已安排好做作业的顺序,对应下标就是指第几天,总共n天*/        int sum=0;       /*下面循环中的i,j都代表第几天*/        for(int i=n;i>=1;i--) //从截至日期最晚的开始,他只能做此日期及之后的作业了       {                                        int maxn=0,p=0;            for(int j=i;j<=n;j++)//此日期之后的作业,这些作业他只能做一个,那就选罚分最大的那个              if(!book[j]&&a[j].deadline>=i&&a[j].score>maxn){ //找最大                  maxn=a[j].score;p=j;//这里的j是i天后的每一天(要包括j==i)因为这一天对应作业的截至日期可能是超规定日期的              }             sum+=maxn;book[p]=1;//book标记是否完成       }       cout<<s-sum<<endl; }return 0;}



0 1
原创粉丝点击