The 35th ACM/ICPC Asia Regional Hangzhou Site —— Online Contest 1006 Fate Stay Night
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3646 这里还可以提交
这个题主要就是用DP,不过动态方程算是比较难想的
int k[100001];
int n;
int m;
int K;
int b[10001];
struct DP
{
int ans;
int blood;
bool operator < (const DP &other) const
{
if (ans != other.ans)
{
return ans < other.ans;
}
else
{
return blood > other.blood;
}
}
}dp[101][10001][2];
// dp[a][b][c]中的a表示用过了a次”Command Mantra“,b表示进行到第b个fire bird
// c为1 时表示进行到第b个fire bird的时候用了”Command Mantra“,0则没有用
void Deal(int tt, DP & r)
{
bool flag = true;
while (tt > 0 && r.ans < K)
{
if (tt > r.blood)
{
tt -= r.blood;
r.ans++;
r.blood = k[r.ans];
}
else if (tt == r.blood)
{
tt = 0;
r.ans++;
r.blood = k[r.ans];
}
else
{
if (flag)
{
r.blood -= tt;
}
tt = 0;
}
flag = false;
}
}
int main()
{
while (1)
{
scanf("%d%d%d", &n, &m, &K);
if (!n && !m && !K)
{
break;
}
int i;
for (i = 0; i < n; i++)
{
scanf("%d", &b[i + 1]);
}
for (i = 0; i < K; i++)
{
scanf("%d", &k[i]);
}
int j;
dp[0][0][0].ans = 0;
dp[0][0][0].blood = k[0];
dp[0][0][1].ans = 0;
dp[0][0][1].blood = k[0];
for (i = 1; i <= n; i++)
{
DP & r = dp[0][i][0];
r.ans = dp[0][i - 1][0].ans;
r.blood = dp[0][i - 1][0].blood;
Deal(b[i], r);
dp[0][i][1].ans = 0;
dp[0][i][1].blood = 0x7fffffff;
}
for (i = 1; i <= m; i++)
{
dp[i][0][0].ans = 0;
dp[i][0][0].blood = k[0];
dp[i][0][1].ans = 0;
dp[i][0][1].blood = k[0];
for (j = 1; j <= n; j++)
{
DP & p = dp[i][j - 1][0] < dp[i][j - 1][1] ? dp[i][j - 1][1] : dp[i][j - 1][0];
DP & q = dp[i][j][0];
q.ans = p.ans;
q.blood = p.blood;
Deal(b[j], q);
DP & w = dp[i][j][1];
DP & e = dp[i - 1][j - 1][0] < dp[i - 1][j - 1][1] ? dp[i - 1][j - 1][1] : dp[i - 1][j - 1][0];
w.ans = e.ans;
w.blood = e.blood;
Deal(2 * b[j], w);
}
}
if (dp[m][n][1] < dp[m][n][0])
{
printf("%d/n", dp[m][n][0].ans);
}
else
{
printf("%d/n", dp[m][n][1].ans);
}
}
}