您的位置:首页 > 其它

HDU 3008 Warcraft,动态规划,滚动数组

2015-08-31 20:36 288 查看
题目地址

之所以总结这道题是因为,这个算是自己想出来的吧,虽然简单但是也是费了不少功夫,的确在确立dp的含义时总是感觉无从下手,不过后来静下来想想居然出来了。

题意:(完全被我改编)回合制游戏,总量固定的HP,SP,普攻与多种技能每次(秒)选一种,BOSS只有普攻,而你有多个技能可选,但耗费SP不同,每秒末SP有少量恢复。每回合以秒为单位,你出招在BOSS前,问最少多少秒胜利。
感受:思考DP时,dp代表什么,可能需要尝试【先确定一个不行了再换,不要不思考】。其实一开始自己没想对但是已确立 dp[x][y]=z,x,y,z分别要代表  剩余SP,BOSS剩余HP,时间t,后来感觉x应该代表t,于是思路才出来。 不知这种题也不知算不算dp,毕竟就相当于罗列出每个时刻所有可能的情况,不过也的确用了已经获得信息。
trick: 滚动数组,还有就是把普攻也算作技能加入技能列表,方便计算。

#include<string.h>
#include<stdio.h>
#define MAXNUM 102

int main(){
int n,t,q;
int i,j,k;
char cost[MAXNUM],power[MAXNUM];
char dp[2][MAXNUM];
int maxt;
int tmp_hp,tmp_sp;
bool f;
while(1){
scanf("%d %d %d",&n,&t,&q);
if( n==0 && n==t && n==q )break;
for(j=0;j<n;j++){    scanf("%d %d",&cost[j],&power[j]);     }
cost
=0; power
=1; //为了方便处理,合并普攻
maxt=99/q+1; //最大时间要求
memset(dp[0],-1,sizeof(dp[0]));
dp[0][100]=100;
f=false;
for(i=1;i<=maxt;i++){
memset(dp[i&1],-1,sizeof(dp[i&1])); //滚动数组
for(k=1;k<=100;k++){
if( dp[ (i+1)&1 ][k] != -1 ){ //两个循环不要反,这里压缩很大
for(j=0;j<=n;j++){
if( k >= cost[j] ){
tmp_hp=dp[ (i+1)&1 ][k]-power[j];
if(tmp_hp<=0){     f=true; break; } //成功
tmp_sp=k-cost[j]+t; //加上每秒补入的能量
if(tmp_sp>100)tmp_sp=100;
if(dp[i&1][tmp_sp]==-1 || dp[i&1][tmp_sp]>tmp_hp){
dp[i&1][tmp_sp]=tmp_hp; //选取最小的加入
}
}
}
if(f)break;
}
}
if(f)break;
}
i>maxt?printf("My god\n"):printf("%d\n",i);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息