D. Lizards and Basements 2(DFS+最优性剪枝)
题目大意:你是火系法师,对面有一排敌人,每个敌人都有HP,你要向他们扔火球,火球对目标 i 有一个主伤害a,对i+1和i -1有一个溅射伤害b。法师只能攻击到2号到n-1号。问你至少要扔多少个火球才能杀死所有敌人,并依次输出每个火球的攻击目标。
题解:数据较少,直接DFS爆搜+最优性剪枝。从第二个开始搜索,确保左边的人死光,然后从满足条件的 i次 开始搜索到i-1,i,i+1个敌人全死的最大次数,往下搜索。找出当前次数最小的ans 存下来,并且把杀敌顺序数据存到vector2。(一次搜索后,返回,状态要恢复) 最优性剪枝:搜索的过程如果次数已经超过当前的最小答案,直接返回,不继续向下搜索。
#include<iostream>
#include<vector>
using namespace std;
int n, a, b,h[20],ans=9999999;
vector<int>v, v2;
int Max(int a, int b);
void dfs(int x, int times);
int main()
{
int i;
cin >> n >> a >> b;
for (i = 1; i <= n; ++i)cin >> h[i];
dfs(2, 0);
cout << ans<<endl;
for (i = 0; i < v2.size(); ++i)
cout << v2[i] << " ";
return 0;
}
int Max(int a, int b)
{
return a > b ? a : b;
}
void dfs(int x, int times)
{
if (times >=ans)return;
if (x == n)
{
if (h[x] < 0)
{
v2 = v;
ans = times;
}
return;
}
int i,j;
for (i = 0; i <= Max(h[x - 1] / b + 1, Max(h[x] / a + 1, h[x + 1] / b + 1)); i++)
{
if (h[x - 1] < b*i)
{
h[x - 1] -= b * i;
h[x] -= a * i;
h[x + 1] -= b * i;
for (j = 0; j < i; ++j)v.push_back(x);
dfs(x + 1, times + i);
for (j = 0; j < i; ++j)v.pop_back();
h[x - 1] += b * i;
h[x] += a * i;
h[x + 1] += b * i;
}
}
}