HDU 2159 FATE by Assassin

来源:互联网 发布:pop3使用的端口号 编辑:程序博客网 时间:2024/06/05 15:20

Problem Description
最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务。久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完这最后一级。现在的问题是,xhd升掉最后一级还需n的经验值,xhd还留有m的忍耐度,每杀一个怪xhd会得到相应的经验,并减掉相应的忍耐度。当忍耐度降到0或者0以下时,xhd就不会玩这游戏。xhd还说了他最多只杀s只怪。请问他能升掉这最后一级吗?

Input
输入数据有多组,对于每组数据第一行输入n,m,k,s(0 < n,m,k,s < 100)四个正整数。分别表示还需的经验值,保留的忍耐度,怪的种数和最多的杀怪数。接下来输入k行数据。每行数据输入两个正整数a,b(0 < a,b < 20);分别表示杀掉一只这种怪xhd会得到的经验值和会减掉的忍耐度。(每种怪都有无数个)

Output
输出升完这级还能保留的最大忍耐度,如果无法升完这级输出-1。

Sample Input

10 10 1 10
1 1
10 10 1 9
1 1
9 10 2 10
1 1
2 2

Sample Output

0
-1
1

思路:
网上好多说用三层循环就行了,化为二维背包问题,他们的思路是
二维完全背包,第二层跟第三层的要顺序循环;(0-1背包逆序循环);状态可理解为,在背包属性为 {m(忍耐度), s(杀怪个数)} 里最多能得到的经验值,之前的背包牺牲体积,这个背包牺牲忍耐度跟个数
注意: 最后扫的时候 外层循环为忍耐度,内层循环为杀怪个数,因为题目要求出剩余忍耐度最大,没有约束杀怪个数,一旦找到经验加满的即为最优解;
状态转移方程为: f[j][k]=max(f[j][k],f[j-v[i]][k-1]+w[i]); w[i]表示杀死第i个怪所得的经验值,v[i]表示消耗的忍耐度
看起来并不需要用三层循环,我们构造一个结构体就好了!
结构体为dp[i]代表如果前i种敌人随便杀,value代最大可以得到的价值,即使完全背包问题,num代表此时杀了多少个怪物。
我们用两层for循环,第一层for(i=1;i<=k;i++)代表随便杀上前i种怪物
第二层for(j=1;j<=m;j++)完全背包,,value代表在忍耐度为j(随便杀前i种怪物)的情况下最多得到多的价值,注意更新条件,价值更新变大及其顺便更新杀敌数目!
核心代码

        for(i=1;i<=k;i++)        {            for(j=1;j<=m;j++)  //表示这么多忍耐范围内可以得到少经验 ,完全背包             {                if(j>=data[i][1]&&dp[j-data[i][1]].value+data[i][0]>    dp[j].value)                {                    dp[j].value=dp[j-data[i][1]].value+data[i][0];                    dp[j].num=dp[j-data[i][1]].num+1;                }            }        }

最后从1到m内输出 m-第一个价值大于等于n且杀敌数小于等于s的位置
讲的不是太好。。。下面看代码。。。

#include<bits/stdc++.h>#define input freopen("input.txt","r",stdin)using namespace std;typedef struct node{    int num;    int value; }node;node dp[1000];int data[1000][2]; // data[i][0]表示可以得到的经验,data[i][1]表示 消耗的耐心程度 int main(){    input;    int n,m,k,s;    int i,j,flag;    while(cin>>n>>m>>k>>s)    {        memset(dp,0,sizeof(dp));        for(i=1;i<=k;i++)        {            cin>>data[i][0]>>data[i][1];         }         for(i=1;i<=k;i++)        {            for(j=1;j<=m;j++)  //表示这么多忍耐范围内可以得到少经验 ,完全背包             {                if(j>=data[i][1]&&dp[j-data[i][1]].value+data[i][0]>    dp[j].value)                {                    dp[j].value=dp[j-data[i][1]].value+data[i][0];                    dp[j].num=dp[j-data[i][1]].num+1;                }            }        }        for(flag=0,i=1;i<=m;i++)        {            if(dp[i].value>=n&&dp[i].num<=s)            {                cout<<(m-i)<<endl;                flag=1;                break;            }        }    if(flag==0)cout<<-1<<endl;    }    return 0;}
0 0
原创粉丝点击