贪心+数据结构-poj 3110 Jenny's First Exam

来源:互联网 发布:软件动态分析工具 编辑:程序博客网 时间:2024/06/04 19:06

题目链接:

http://poj.org/problem?id=3110

题目意思:

有n科考试,每科考试可以提前di天复习,每科考试只需一天复习,而且要求不能早于考试前di天复习。考试那天不能复习。给n科考试日期,求最晚开始复习的日期。

解题思路:

先把日期全部转化成与0000年00月00日的天数差,然后依据考试时间从晚到早排序,从后往前扫描天数,如果当前天为考试日期,则把该考试的科目加到以按最早复习时间从后往前排序的优先队列,如果当前天没有考试,则从队列中取出队头(表示最晚复习的科目),如果当前时间小于它,则表示不能完成,否则复习该科目。

PS:

1、这种贪心的方式很巧妙,按天数来处理。

2、把天数对应成日期,可以以500年为一个周期,加速处理。

详细解释的代码:

#include<iostream>#include<cmath>#include<cstdio>#include<sstream>#include<cstdlib>#include<string>#include<string.h>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<set>#include<stack>#include<list>#include<queue>#include<ctime>#include<bitset>#define eps 1e-6#define INF 0x3f3f3f3f#define PI acos(-1.0)#define ll __int64#define LL long long#define lson l,m,(rt<<1)#define rson m+1,r,(rt<<1)|1#define M 1000000007#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define Maxn 55000int n;int yd[2]={365,366};int days[2][13]={0,31,28,31,30,31,30,31,31,30,31,30,31,0,31,29,31,30,31,30,31,31,30,31,30,31};struct DD{    int m,d,y;};struct Sub{    int cur,ea;    char save[25];    int dd;}sub[Maxn];bool cmp1(struct Sub a,struct Sub b) //按考试日期从晚到前排序{    return a.cur>b.cur;}int isleap(int y) //是否是润年{    if((y%4==0&&y%100)||(y%400==0))        return 1;    return 0;}int dtoi(int y,int m,int d) //将日期转化成距0000年00月00日的天数{    int res=0,yy=isleap(y);    res+=y*365+(y-1)/4-(y-1)/100+(y-1)/400; //从第0年开始    for(int i=1;i<m;i++)        res+=days[yy][i];    return res+d-1; //注意0表示第一天 1表示第2天}//500年一算 182621DD itod(int cur){    DD res;    int i;    res.y=cur/182621*500; //也从0开始记 500年为基本单位    for(cur=cur%182621;cur>=yd[isleap(res.y)];res.y++)        cur-=yd[isleap(res.y)];    for(i=1;cur>=days[isleap(res.y)][i];i++)        cur-=days[isleap(res.y)][i];    res.m=i;    res.d=cur+1; //由于有求于 有0所以加1    return res;}struct Inf  //优先队列 按最早复习时间 从晚到前 排序{    int d;    friend bool operator < (struct Inf a,struct Inf b)    {        return a.d<b.d;    }};int main(){   //freopen("in.txt","r",stdin);   //freopen("out.txt","w",stdout);//   int sum=0;//   for(int i=1;i<=500;i++)//        sum+=yd[isleap(i)];//   printf("%d\n",sum);    //DD dd=itod(0);   // printf("%04d.%02d.%02d\n",dd.y,dd.m,dd.d);   while(~scanf("%d",&n))   {       for(int i=1;i<=n;i++)       {           scanf("%s",sub[i].save);           int y,m,d;           scanf("%2d.%2d.%4d",&d,&m,&y);           sub[i].cur=dtoi(y,m,d);           scanf("%d",&sub[i].dd);           sub[i].ea=sub[i].cur-sub[i].dd;       }       sort(sub+1,sub+1+n,cmp1);//       for(int i=1;i<=n;i++)//           printf("%d ",sub[i].cur);       priority_queue<struct Inf>myq;       int la=sub[1].cur,s=1,e=n,le=n;       bool ans=false;       while(la) //从后往前扫描天数       {           bool ha=false;           if(sub[s].cur==la) //如果有考试           {               struct Inf temp;               temp.d=sub[s].ea;               myq.push(temp); //把考试加到优先队列里               ha=true;               s++;           }           if(!ha)  //如果没有考试           {               if(!myq.empty()) //是否有考试没复习               {                   struct Inf temp=myq.top();                   myq.pop();                   if(temp.d<=la) //满足复习的条件                        le--;                   else                   {                       ans=true; //不行 肯定不能完成                       printf("Impossible\n");                       break;                   }               }           }           if(!le) //所有科目都复习完了           {               DD tt=itod(la);               ans=true;               printf("%02d.%02d.%04d\n",tt.d,tt.m,tt.y);               break;           }           la--;       }       if(!ans) //可能考试重复了            printf("Impossible\n");   }   return 0;}/*693963 693961 693960 Impossible*/



0 0
原创粉丝点击