Gym的题面全是PDF不好复制。。。原题链接戳这里。
题目大意:若干年后,考古学家发现了一堆关于假日的记载,这些记载只有月日,没有年份。记载了假日的取消和颁布。这些记载是按照时间顺序给出的,同一天里只能颁布一条法令。给定一个时间范围,问如何安排记载发布的年份,使得在这个范围中假日的时间最长。
思路:求时间最长,一看就是一个DP,我们令f[i][j]表示处理完前i个记载,最后一个记载发布在j年的时候,假日最多多长。不难看出转移方程:f[i][j]=max{f[i-1][k]±(t-k)}(此处±分别为颁布或删除假日,另外要分别处理颁布日在假日前后两种可能,单独处理闰年).最后答案ans=max{ans,f[n][i](i=0 to t)}.求出解后不难看出,我们不好输出答案。就再开一个数组,令g[i][j]表示f[i][j]是从f[i-1]的哪一个地方转移来的,即若f[i][j]=f[i-1][k],令g[i][j]=k,最后递推输出结果即可。
本题要加freopen,切记!不然会RE。。。这个题很考验字符串的读入。。然而本垃圾并不会字符串的相关操作,所以判断月份就写了将近一百行。。。三百行代码其实没多少干货。。不喜勿喷。
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<ctime>
using namespace std;
const int MAXN=110;
const int INF=1e9;
const char Mon[13][15]={"","January","February","March","April","May"
,"June","July","August","September","October","November","December"};
int month1[MAXN],day1[MAXN],month2[MAXN],day2[MAXN];
int ad[MAXN];
int f[MAXN][MAXN],g[MAXN][MAXN];
void getmonth1(int pos,char y[15])
{
if (y[0]=='J')
{
if (y[1]=='a')
{
month1[pos]=1;
}
else if (y[2]=='n')
{
month1[pos]=6;
}
else
{
month1[pos]=7;
}
}
else if (y[0]=='F')
{
month1[pos]=2;
}
else if (y[0]=='M')
{
if (y[2]=='r')
{
month1[pos]=3;
}
else
{
month1[pos]=5;
}
}
else if (y[0]=='A')
{
if (y[1]=='p')
{
month1[pos]=4;
}
else
{
month1[pos]=8;
}
}
else if (y[0]=='S')
{
month1[pos]=9;
}
else if (y[0]=='O')
{
month1[pos]=10;
}
else if (y[0]=='N')
{
month1[pos]=11;
}
else
{
month1[pos]=12;
}
}
void getmonth2(int pos,char y[15])
{
if (y[0]=='J')
{
if (y[1]=='a')
{
month2[pos]=1;
}
else if (y[2]=='n')
{
month2[pos]=6;
}
else
{
month2[pos]=7;
}
}
else if (y[0]=='F')
{
month2[pos]=2;
}
else if (y[0]=='M')
{
if (y[2]=='r')
{
month2[pos]=3;
}
else
{
month2[pos]=5;
}
}
else if (y[0]=='A')
{
if (y[1]=='p')
{
month2[pos]=4;
}
else
{
month2[pos]=8;
}
}
else if (y[0]=='S')
{
month2[pos]=9;
}
else if (y[0]=='O')
{
month2[pos]=10;
}
else if (y[0]=='N')
{
month2[pos]=11;
}
else
{
month2[pos]=12;
}
}
bool check(int year)
{
if (year%100==0)
{
if (year%400==0)
{
return 1;
}
return 0;
}
if (year%4==0)
{
return 1;
}
return 0;
}
bool after(int m1,int d1,int m2,int d2)
{
if (m2>m1)
{
return 1;
}
else if (m2<m1)
{
return 0;
}
if (d1<d2)
{
return 1;
}
else
{
return 0;
}
}
void print(int n,int start,int pos)
{
if (n>1)
{
print(n-1,start,g[n][pos]);
}
printf("%s %d %d, ",Mon[month2[n]],day2[n],start+pos);
if (ad[n]==1)
{
printf("added ");
}
else
{
printf("removed ");
}
printf("%s %d\n",Mon[month1[n]],day1[n]);
}
int main()
{
freopen("holidays.in","r",stdin);
freopen("holidays.out","w",stdout);
int start,end;
int n;
scanf("%d%d",&start,&end);
int t=end-start;
scanf("%d",&n);
memset(f,0,sizeof(f));
for (int i=1;i<=n;i++)
{
for (int j=0;j<=t;j++)
{
f[i][j]=-INF;
}
}
for (int i=1;i<=n;i++)
{
char c,tmp[15];
scanf("%s",tmp);
getmonth2(i,tmp);
scanf("%d",&day2[i]);
getchar();getchar();
c=getchar();
if (c=='a')
{
ad[i]=1;
}
else
{
ad[i]=-1;
}
scanf("%s",tmp);
scanf("%s",tmp);
getmonth1(i,tmp);
scanf("%d",&day1[i]);
bool nowadd=after(month2[i],day2[i],month1[i],day1[i]);
bool b=after(month2[i-1],day2[i-1],month2[i],day2[i]);
b=!b;
int d=0;
for (int j=t;j>=0;j--)
{
if (nowadd)
{
if (month1[i]!=2 || day1[i]!=29 || check(start+j))
{
d+=ad[i];
}
}
for (int k=j-b;k>=0;k--)
{
if (f[i][j]<=f[i-1][k]+d)
{
f[i][j]=f[i-1][k]+d;
g[i][j]=k;
}
}
if (!nowadd)
{
if (month1[i]!=2 || day1[i]!=29 || check(start+j))
{
d+=ad[i];
}
}
}
if (month2[i]==2 && day2[i]==29)
{
for (int j=0;j<=t;j++)
{
if (!check(j+start))
{
f[i][j]=-INF;
}
}
}
}
int maxx=f[n][0],Pos=0;
for (int i=1;i<=t;i++)
{
if (f[n][i]>maxx)
{
maxx=f[n][i];
Pos=i;
}
}
if (f[n][Pos]<0)
{
cout<<-1<<endl;
}
else
{
cout<<maxx<<endl;
print(n,start,Pos);
}
return 0;
}