定义状态dp[i][j][t]代表前i种攻击,当前怪物生命值为j,防御力为t,所需要的最小代价。
利用完全背包的方法很容易得到
(p[i] = 第i种方法的攻击值减去防御值t)
dp[i][j][t] = min(dp[i - 1][j][t], dp[i][j - p[i]] + k[i])
可以写成滚动数组的形式。
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N = 100005;
const int INF = 0x3f3f3f3f;
int n, m;
int a[N], b[N];
int k[1005], p[1005];
LL dp[1005][15];
int main()
{
//freopen("test.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
cin.sync_with_stdio(false);
while (cin >> n >> m)
{
for (int i=1; i<=n; i++)
cin >> a[i] >> b[i];
for (int i=1; i<=m; i++)
cin >> k[i] >> p[i];
memset(dp, 0, sizeof(dp));
for (int t=0; t<=10; t++)
for (int i=1; i<=m; i++)
for (int v=1; v<=1000; v++)
{
int x = p[i] - (t > p[i] ? p[i] : t);
if (i == 1)
{
if (x)
dp[v][t] = (v / x + (v % x ? 1 : 0)) * k[i];
else
dp[v][t] = INF;
}
else
dp[v][t] = min(dp[v][t], (v >= x ? dp[v - x][t] : 0) + k[i]);
}
LL ans = 0;
for (int i=1; i<=n; i++)
{
if (dp[a[i]][b[i]] < INF)
ans += dp[a[i]][b[i]];
else
{
ans = -1;
break;
}
}
cout << ans << endl;
}
return 0;
}