HDU 1176 免费馅饼
感谢sjy巨巨的帮助,一开始知道这是一道dp题但就是找不到思路,经过sjy巨巨的指点才搞懂。
这道题是以每一秒为一个状态,遍历一遍坐标,状态是从最后一秒往前遍历。
就样例来说的话,最后一秒是第3秒,坐标是8。那么此时的状态可以由第2秒的时间,坐标7,8,9三个位置过来。
用一个二维数组,下标分别表示时间 t 和 位置 x。可以得到 dp[x][t]=max( dp[x][t],dp[y][t-1]+dp[x][t] ) 『y 从 x-1 循环到x+1,因为x的位置可以由这三个位置到达』;
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int dp[100010][15]; int t,n,x,y; int main() { while(scanf("%d",&n)!=EOF,n) { int mm=0; memset(dp,0,sizeof(dp)); for(int i=0; i<n; i++) { scanf("%d%d",&x,&y); dp[y][x+1]++; //这个地方也是sjy同学想出来的,因为在0和10的位置上分别只能由 -1,1,2 和9,10,11到达, //而-1和11都不存在,所以可以看着是0。也就是说从-1 11到达0和10的时候本身提供的价值就是0; //and 因为数组的最小值是0,不存在-1 所以右移一位,让x=0,代替x=-1的位置。 mm=max(y,mm); } for(int i=mm-1; i>=0; i--) { for(int j=1; j<=11; j++) { for(int k=j-1; k<=j+1; k++) { dp[i][j]=max(dp[i][j],dp[i+1][k]+dp[i][j]); } } } printf("%d\n",dp[0][6]); } return 0; }