注意点:
time=1:活动范围为4-6;
time=2:3-7;
time=3:2-8;
time=4:1-9;
time=5:0-10(全范围)
突破口:
状态:dp[i,j]在i秒,j位置能获得的最大饼数
状态转移方程:
dp[i,j]=max(dp[i-1,j],dp[i-1,j-1],dp[i-1,j+1]);
此题涉及到一些代码技巧,要多注意。
代码如下:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int dp[100001][11],a[11]; //a[i]为辅助数组,记录某一时刻,i位置饼的数量
struct bing
{
int p;
int t;
}b[100001];
bool cmp(bing x,bing y) //按掉落时间从小到大排序
{
if(x.t!=y.t)
return x.t<y.t;
return x.p<y.p;
}
int main()
{
int n,i,j,k;
int time,Time,ans,step; //Time记录最大时长,step相当于前文说到的time,time表示某个饼掉落的时间
while(~scanf("%d",&n)&&n)
{
Time=ans=k=step=0;
for(i=0;i<=n-1;i++)
{
scanf("%d%d",&b[i].p,&b[i].t);
if(Time<b[i].t)
Time=b[i].t;
}//printf("%d\n",Time);
sort(b,b+n,cmp);
for(i=0;i<=Time;i++) //初始化
{
for(j=0;j<=10;j++)
dp[i][j]=0;
}
for(i=1;i<=Time;i++)
{
step++;
memset(a,0,sizeof(a)); //每次都要初始化
time=b[k].t;
if(i==time) //当前时间i=time表明现在有饼掉落,这时才需要记录有多少个饼
{
while(time==b[k].t)
{
a[b[k].p]++;
k++;
if(k>n-1) //k>n-1了,此时一定要结束循环了,否则会报错!!!!!
break;
}
}//printf("%d %d\n",dp[Time][5],dp[0][5]);
if(step==1)
for(j=4;j<=6;j++)
dp[i][j]=max(dp[i-1][j-1],max(dp[i-1][j],dp[i-1][j+1]))+a[j];
else if(step==2)
for(j=3;j<=7;j++)
dp[i][j]=max(dp[i-1][j-1],max(dp[i-1][j],dp[i-1][j+1]))+a[j];
else if(step==3)
for(j=2;j<=8;j++)
dp[i][j]=max(dp[i-1][j-1],max(dp[i-1][j],dp[i-1][j+1]))+a[j];
else if(step==4)
for(j=1;j<=9;j++)
dp[i][j]=max(dp[i-1][j-1],max(dp[i-1][j],dp[i-1][j+1]))+a[j];
else
for(j=0;j<=10;j++)
if(j==0)
dp[i][j]=max(dp[i-1][j],dp[i-1][j+1])+a[j];
else if(j==10)
dp[i][j]=max(dp[i-1][j],dp[i-1][j-1])+a[j];
else dp[i][j]=max(dp[i-1][j-1],max(dp[i-1][j],dp[i-1][j+1]))+a[j];
// printf("%d %d\n",dp[Time][5],dp[0][5]);
}
for(i=0;i<=10;i++)
if(dp[Time][i]>=ans)
ans=dp[Time][i];
printf("%d\n",ans);
}
return 0;
}
补充:其实这道题也可以像数塔一样做,后面有空试着A一下。