题意很明显,就不细说了
我们这里可以把剩下的忍耐度看作背包容量,然后价值就是杀了怪所得的经验
用第二维表示杀了q只怪,这样就能用dp[j][q]表示已消耗j点忍耐度,杀了q只怪时的经验值
状态转移方程
a[i]表示杀死i怪物所获得的经验
b[i]表示杀死i怪物所消耗的忍耐值
对于第i个怪物:
(1)杀:此时我们消耗点忍耐度,同时击杀怪物数+1,并且获得a[i]点经验
(2)不杀:此时我们忍耐度不变,击杀怪物数不变,由于空间已经优化到二维,所以有dp[j][q]=dp[j][q]
综合即为上述状态转移方程
代码如下:
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#define For(a,b) for(int a=0;a<b;a++)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn = 1e2+10;
const int INF = 0x3f3f3f3f;
const int inf = 0x3f;
const double EPS = 1e-7;
const int MOD = 1e9+7;
int dp[maxn][maxn];
int a[maxn];
int b[maxn];
int n,m,k,s;
int main()
{
while(cin >> n >> m >> k >> s){
mem(dp,0);
For(i,k)
cin >> a[i+1] >> b[i+1];
for(int i=1;i<=k;i++)
for(int j=b[i];j<=m;j++)
for(int q=1;q<=s;q++)
dp[j][q] = max(dp[j][q],dp[j-b[i]][q-1]+a[i]);
int ans = -1;
for(int j=1;j<=m;j++) //从小->大寻找,满足所需经验就break
if(dp[j][s]>=n){
ans = m-j;
break;
}
cout << ans<<endl;
}
return 0;
}