這個題由於變量比較多。 所以容易搞複雜。 其實看明白了 還是一個揹包問題。
但是這個明顯就是 一種怪可以打很多個了。
有一個細節需要注意。被這個細節坑了一發。 那就是 當 它的 經驗超過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;
}