题意:勇者去打怪兽,有两个值,一个是能量条,初始100,debuff毒素条,一开始0。每个样例的第一行是打一个怪兽需要的能量和时间。第二行是勇者带的药的瓶数。接下来一行给的是每瓶药可以加的能量,然后一行是每瓶药会增加的毒素值。每次打完怪,勇者可以喝最多一瓶药,或者不喝。当勇者能量<=打怪需要的能量的时候,就不能开怪了,不能开怪就结束了,还有毒素,超过100他也死了。打怪的时候,过多少时间,-多少毒素值,毒素值最低0,能量最多100。
思路:首先注意一下debuff毒素条最多99,100就gg了,训练写这题的时候我以为是最多100,结果wa了,被队友吐槽死了QAQ
然后由于最多8瓶药,就考虑状压一下喝药状态。然后还有两维放能量和毒素,最后一维放这一场boss战喝没喝药,然后暴力跑dp就行了。
代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#include<map>
#include<vector>
#include<set>
#include<queue>
using namespace std;
const int maxn = 110;
const int inf = 0x3f3f3f3f;
int c,kk,m,n,dp[1<<9][maxn][maxn][2];
struct node
{
int en, po;
}med[10];
int main()
{
scanf("%d", &c);
while (c--)
{
scanf("%d %d", &kk, &m);
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d", &med[i].en);
}
for (int i = 1; i <= n; i++)
{
scanf("%d", &med[i].po);
}
memset(dp, -inf, sizeof(dp));
dp[0][100][0][0] = 0;
int A = 0;
for (int i = 0; i <= (1 << n) - 1; i++)
{
for (int j = 100; j >= 1; j--)
{
for (int k = 99; k >= 0; k--)
{
for (int q = 0; q <= 1; q++)
{
if (dp[i][j][k][q] < 0)
continue;
if (j > kk)//能量足够打败怪兽
{
dp[i][j-kk][max(0,k-m)][0] = max(dp[i][j][k][q]+1, dp[i][j - kk][max(0, k - m)][0]);
A = max(A, dp[i][j - kk][max(0, k - m)][0]);
}
if (q == 1)
continue;
for (int w = 1; w <= n; w++)
{
int id = 1 << (w - 1);
if (id&i || k + med[w].po >= 100)//吃过或者毒素>=100
continue;
int now = id | i;
dp[now][min(100,j+med[w].en)][k+med[w].po][1] = max(dp[now][min(100, j + med[w].en)][k + med[w].po][1], dp[i][j][k][q]);
A = max(A, dp[now][min(100, j + med[w].en)][k + med[w].po][1]);
}
}
}
}
}
printf("%d\n", A);
}
return 0;
}