没听说过二维dp前根本想不出来啊!!!!
下面附上老师结合本题对二维dp讲解:
通常而言,如果用1个整数状态的方程 写不出来,就用2个整数,也就是升维
•2个写不出来,就用3个,以此类推
•但是升维会严重消耗时空,通常需要 结合数据范围来进行判定:
•到底是应该升维还是需要寻找更巧妙 的状态表示与规划目标
•在接馅饼这道题中,馅饼的数量显然 与位置也有关
•因此这道题的状态要用2个数表示,目 标记作Dtx,Dtx表示在t时刻、x位置能 够接到的最大数量
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define MAXN 100010
using namespace std;
int dp[MAXN][12],pile[MAXN][12];
///全局变量和静态变量的存储区域是在一起的,程序结束后由系统释放。数据区的大小由系统限定,一般很大。
int max_is(int a,int b,int c);
int main(){
int n,x,t,i,j,maxt;
while(scanf("%d",&n)!=EOF&&n){
memset(dp,0,sizeof(dp));
memset(pile,0,sizeof(pile));
maxt=0;
for(i=0;i<n;i++){
scanf("%d%d",&x,&t);
pile[t][x]++;
if(maxt<t) maxt=t;
}
for(i=1;i<=11;i++)
dp[maxt][i]=pile[maxt][i];//移动结束的时候的时间总是最晚的那个馅饼落下的时间
for(i=maxt-1;i>=0;i--)//最晚时刻在上面循环的初始化好了,从最晚时刻前面一秒开始dp到时间为0的地方,即dp【0】【5】
{
for(j=0;j<11;j++)
{
if(j==0) dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+pile[i][j];//处理在边界的特殊情况
else dp[i][j]=max_is(dp[i+1][j-1],dp[i+1][j],dp[i+1][j+1])+pile[i][j];/*一般情况怎么dp。i时间,j位置。
后面的状态无非是前面的左移1,右移1,不动三种操作中的一种得到,取max再加上该点掉的馅饼*/
}
}
printf("%d\n",dp[0][5]);
}
return 0;
}
int max_is(int a,int b,int c){
return max(a,max(b,c));
}
到这篇博客,我半个月刷的代表性题目也贴完了,最后还是因为种种原因 (就是菜) 放弃了acm。
其实做这些题大部分都参考了别人的思路和代码,甚至有些就是理解后再背着敲出来的,但还是会有些错误自己debug了很久,综上感觉可能自己真的不太适合acm吧,但每次ac带来的感动我也体验过了hhhh。以后还是会有算法题的博客的,当然可能都会是些不太难比较适合非acmer的算法题了,我也会保持我的带有自我理解的详细注释的(虽然自己感觉清楚,但是可能别人都看不懂我再说啥hhhh,表达也是门功夫啊),业余刷刷简单算法也不错嘛。就酱,再见。