Problem HDU-1176 免费的馅饼 DP
题目链接:这里写链接内容
题析:
dp题最主要的是抓住 状态 ,也就是题目的目的 。这个题就是 要求的位置上 最多的馅饼数 。再 考虑条件:起点在5;一秒的时间,只能移到相邻的点 ——(左、它、 右)。由于起点知道,终点未知 ,我们就可以用for倒推,不断的更新前一时间的状态。
dp[i][j] ,即第 j秒 第 i 个位置所获得的 馅饼数 ,其中 i 表示位置,j 表示时间 然后,把此刻此位置的状态dp与这秒后一秒(j+1)的这三点(此点 、左右相邻的俩点)的状态dp相比较:
dp[i][j] = Max(dp[i-1][j+1], dp[i][j+1], dp[i+1][j+1] ) + dp[i]
备注:之前WA了几次,就是由于没把边界考虑进去,想想,这是1-10的十个点,如果正好是边界情况的话,与之相邻的点只有一个,也就是只要比较俩点 。
本题用scanf读入,别用cin。
具体的代码如下:
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
const int MAX=100010;
int dp[14][MAX];
int Max (int x,int z){
return x>z? x:z;
}
int main(){
int n,x,t,m,loca,second,tmax;
// dp 表示在第j秒 第i个位置所获得的馅饼数
while(~scanf("%d",&n)&&n){
tmax = -1;
memset(dp,0,sizeof(dp));
while(n--){
scanf("%d %d",&x,&t);
// if(x<0||x>10) continue;
dp[x][t]++; //[i][j]
tmax = Max(t,tmax);
}
for(second=tmax-1;second>=0;second--){ //表示在第j秒 第i个位置所获得的馅饼数
for(loca=0;loca<=10;loca++){ //跳过0位置 可能0之前的未被初始化
if(loca==0) dp[loca][second] += Max(dp[loca][second+1],dp[loca+1][second+1]);
else if(loca==10) dp[loca][second] += Max(dp[loca][second+1],dp[loca-1][second+1]);
else dp[loca][second] += Max(dp[loca-1][second+1],Max(dp[loca][second+1],dp[loca+1][second+1]));
//printf("第%d位置第%d秒 %d \n",loca,second,dp[loca][second]);
}
}
printf("%d\n",dp[5][0]);
}
return 0;
}
这是第一次AC交的,看着舒服些,精简版:
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
const int MAX=100010;
int dp[14][MAX];
int Max (int x,int z){
return x>z? x:z;
}
int main(){
int n,x,t,m,i,j,tmax;
// dp 表示在第j秒 第i个位置所获得的馅饼数
while(~scanf("%d",&n)&&n){
tmax = -1;
memset(dp,0,sizeof(dp));
while(n--){
scanf("%d %d",&x,&t);
dp[x+1][t]++; //[i][j]
tmax = Max(t,tmax);
}
for(j=tmax-1;j>=0;j--){ //表示在第j秒 第i个位置所获得的馅饼数
for(i=1;i<12;i++){
dp[i][j] += Max(dp[i-1][j+1],Max(dp[i][j+1],dp[i+1][j+1]));
}
}
printf("%d\n",dp[6][0]);
}
return 0;
}
/*
6
5 1
4 1
6 1
7 2
7 2
8 3
0
*/

本文详细解析了HDU-1176免费的馅饼DP问题,通过动态规划方法求解如何在限定时间内获取最多数量的馅饼,介绍了状态转移方程,并给出了两种实现代码。
3889

被折叠的 条评论
为什么被折叠?



