hdu3646 Fate Stay Night(dp,读题障碍)

47 篇文章 0 订阅
题目大意:
剑客VS狂战士。剑客的招数是依次召唤 N只火鸟攻击(为啥不叫召唤师),火鸟体力不一定相同。而狂战士有 K条命,火鸟一滴血换狂战士一滴血,直到一方体力为0。狂战士体力为0并且还有剩余生命则涅槃重生。火鸟刚招出来是YoungBrid,若杀死过狂战士,则变成OldBrid。剑客可以使用 M次咒语,每次可以使当前火鸟的体力*2。(要求最优状态,则肯定是在刚放出火鸟时施放咒语)
攻击规则:   (m为鸟还剩体力,n为狂战士当前生命还剩体力)
1. m>n。则狂战士重生(如果可以的话),鸟体力变为m-n(如果是YoungBird则变为OldBrida)。
2. m=n。则狂战士重生(如果可以的话),鸟体力变为0,然后挂掉。
3. m<n。如果鸟为OldBrid,则直接挂掉,狂战士无损伤。如果为YoungBrid,则换掉狂战士m滴血,然后挂掉。
前提:只有在刚放出一只火鸟,或者狂战士重生才会触发攻击规则。(即不存在攻击中的状态)

最后,输出N只火鸟最多能和谐掉狂战士多少条命。(转自大神:http://blog.sina.com.cn/s/blog_5e8c2b4e01010fbo.html)

dp[i][j] = max(dp[i-1][j]+第i只鸟不使用double可杀死的怪兽数, dp[i-1][j-1]+第i只鸟使用double可杀死的怪兽数)

dp[i][j]指前i只鸟使用j次double可杀死的怪兽数

#include <iostream>  
#include <cstdio>  
#include <cstring>  
#include <algorithm>  
using namespace std;  
  
int dp[10010][110],rest[10010][110];  
int ac[10010],bc[100010],n,m,k;  
int cc(int acc, int &bcc, int now)  
{  
    int flag = 1;  
    while(now < k)  
    {  
        if(acc > bcc)  //m>n
        {  
            acc -= bcc;  
            now++;  
            bcc = bc[now+1];  
            flag = 0;  
        }  
        else if(acc == bcc)  //m==n
        {  
            now++;  
            bcc = bc[now+1];  
            break;  
        }  
        else if(flag)  //m<n且还是YoungBrid
        {  
            bcc -= acc;  
            break;  
        }  
        else  //m<n且已经是OldBrid
            break;  
    }  
    return now;  
}  
  
int main()  
{  
    while(scanf("%d%d%d",&n,&m,&k) == 3 && n+m+k)  
    {  
        for(int i = 1; i <= n; i++)  
            scanf("%d",&ac[i]);  
        for(int i = 1; i <= k; i++)  
            scanf("%d",&bc[i]);  
        memset(dp, 0, sizeof(dp));  
        m = min(m, n);  
        rest[0][0] = rest[0][1] = bc[1];  
        for(int i = 1; i <= n; i++)  
        {  
            int res = rest[i-1][0];  
            dp[i][0] = cc(ac[i], res, dp[i-1][0]);  
            rest[i][0] = res;  
            for(int j = 1; j <= min(m, i); j++)  
            {  
                int res1 = rest[i-1][j], res2 = rest[i-1][j-1];  
                int k1 = cc(ac[i], res1, dp[i-1][j]), k2 = cc(ac[i]*2, res2, dp[i-1][j-1]);  
                if(k1 > k2)  
                {  
                    dp[i][j] = k1;  
                    rest[i][j] = res1;  
                }  
                else if(k1 < k2)  
                {  
                    dp[i][j] = k2;  
                    rest[i][j] = res2;  
                }  
                else  
                {  
                    dp[i][j] = k1;  
                    rest[i][j] = min(res1, res2);  
                }  
            }  
        }  
        printf("%d\n",dp[n][m]);  
    }  
    return 0;  
}  


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值