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

题目地址

之所以总结这道题是因为,这个算是自己想出来的吧,虽然简单但是也是费了不少功夫,的确在确立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[n]=0; power[n]=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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值