Hdu 2809 God of War (DP_状态压缩DP

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2809

题目大意:奥特曼很牛逼,要单挑n只怪兽。怪兽和奥特曼一样都有hp、攻击力、防御力,奥特曼有一个经验值属性,通过打怪兽获得经验值超过100就升级,升级时hp加一些,攻击力加一些,防御力加一些,回不到满血状态,奥特曼每次都要和怪兽血拼,奥特曼先打,怪兽后打,直到一方倒下为止。问奥特曼能不能打倒所有的怪兽从而拯救地球?可以的话输出剩下的最大hp。

解题思路:题目看起来很雷人,实际上就是普通的TSP,只是每次状态转移略显麻烦些。为什么可以转换为TSP呢?因为每只怪兽都只要打一次,而且打完若干只怪兽后剩下的经验值、攻击力、防御力都是一样的,只有hp会随顺序改变,那么用一个数组dp[i]表示i状态时的最多hp,每次更新都去计算i状态下的各项属性。我把hp,at,def,ex都封装进一个结构体,意思是一样的,状态转移见代码。


测试数据:

100  80  100  5  5  5
2
ZhangFei 95  75  100  100 
XuChu 90  90  100  90

100 75 100 5 5 5
1
GuanYu 95 85 100 100


C艹代码:

#include <stdio.h>
#include <string.h>
#define MIN 21
#define MAX 1<<21
#define max(a,b) (a)>(b)?(a):(b)


struct node {

    int at,def,hp,ex;
}dp[MAX],enemy[MIN],add;
int n,m,state,ans;


void State_Dp() {

    int i,j,k,meat,heat,mtime,htime;
    int curhp,curex,curat,curdef;


    for (i = 0; i < (1<<n); ++i)
        for (j = 0; j < n; ++j)
            if (!(i & (1<<j)) && dp[i].hp) {

                meat = max(1,dp[i].at - enemy[j].def);          //我们打对方多少hp
                heat = max(1,enemy[j].at - dp[i].def);          //对方打我们多少hp
                mtime = (dp[i].hp + heat - 1) / heat;           //我们能撑住几次攻击
                htime = (enemy[j].hp + meat - 1) / meat;        //对方能撑住几次攻击


                if (mtime < htime) continue;                  //我们先倒下
                curhp = dp[i].hp - (htime - 1) * heat;        //攻击完的状态
                curex = dp[i].ex + enemy[j].ex;
                curat = dp[i].at,curdef = dp[i].def;
                if (curex >= 100) {                           //升级

                    curex -= 100;
                    curhp += add.hp;
                    curat += add.at;
                    curdef += add.def;
                }
                

                if (curhp >= dp[i|(1<<j)].hp) {             //更新答案

                    dp[i|(1<<j)].hp = curhp;
                    dp[i|(1<<j)].ex = curex;
                    dp[i|(1<<j)].at = curat;
                    dp[i|(1<<j)].def = curdef;
                }
            }
}


int main()
{
    int i,j,k;
    char tp[30];


    while (scanf("%d%d%d",&dp[0].at,&dp[0].def,&dp[0].hp) != EOF) {

        dp[0].ex = 0;
        scanf("%d%d%d",&add.at,&add.def,&add.hp);
        scanf("%d",&n);
        for (i = 0; i < n; ++i)
            scanf("%s %d%d%d%d",tp,&enemy[i].at,&enemy[i].def,&enemy[i].hp,&enemy[i].ex);

        
        for (i = 1; i < (1<<n); ++i) dp[i].hp = 0;
        State_Dp();
        if (dp[(1<<n)-1].hp) printf("%d\n",dp[(1<<n)-1].hp);
        else printf("Poor LvBu,his period was gone.\n");
    }
}

本文ZeroClock原创,但可以转载,因为我们是兄弟。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值