您的位置:首页 > 其它

HDU 2159 FATE(二维dp背包)

2014-11-05 17:22 405 查看
这个题由于变量比较多。 所以容易搞复杂。 其实看明白了 还是一个背包问题。

但是这个明显就是 一种怪可以打很多个了。

有一个细节需要注意。被这个细节坑了一发。 那就是 当 它的 经验超过n的时候 也是可以升级的。 比如 经验需要3 有一种 可以得到经验2 的怪。 那就必须杀两个得到4个经验

才能升级。 而我第一次写的代码就是 只判断了 3的情况。 所以就错了。我往后推了一步。因为经验最多就是20. 那我 直接得出 n----n+20之间的所有情况就好了

递推公式比较好写。 我用 d【i】【j】 表示 i经验 j个怪的时候 所能用的最小忍耐度。

不过A了之后 去看别人写的题解。 发现 用 d【i】【j】 表示 i 忍耐度 j个怪的时候 如果经验 大于等于 n的时候 就是最优解。 这个好像更简单 更好理解

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <fstream>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <list>
#include <vector>
#include <cmath>
#include <iomanip>
#include <cmath>
typedef long long LL;
typedef unsigned long long LLU;
const double PI=acos(-1.0);
using namespace std;
#define MAXN 100+21
#define INF 1 << 30
int d[MAXN][MAXN] = {0};
struct Game{
    int v;
    int de;
};
int main (){
    int n,m,k,s;
    while(scanf("%d%d%d%d",&n,&m,&k,&s) != EOF){
        for(int i = 0; i < MAXN; i++){
            for(int j = 0 ;j < MAXN; j++)
                d[i][j] = INF;
        }
        Game g[MAXN];
        for(int i = 1; i <= k; i++)
            scanf("%d%d",&g[i].v,&g[i].de);
        d[0][0] = 0;
        for(int i = 0; i <= n+20; i++){
            for(int j = 1; j <= s; j++){
                for(int z = 1; z <= k; z++){
                    if(i-g[z].v >= 0 && d[i-g[z].v][j-1]+g[z].de <= m && d[i-g[z].v][j-1] != INF)
                        d[i][j] = min(d[i][j],d[i-g[z].v][j-1]+g[z].de);
                }
            }
        }
        int M = INF;
        for(int j = n; j <= n+20; j++){
            for(int i = 0; i <= s; i++)
                M = min(M, d[j][i]);
        }
        if(M > m)
            printf("-1\n");
        else
            printf("%d\n",m-M);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: