题目链接:
思路:
看到数据不大,直接枚举每个位置的攻击次数即可。注意左边的弓箭手必须打死,另外,到n-1位置时,还必须把n-1和n都打死。
这题还有dp的做法,不过我没想出来,可能之后会补充上。
代码:
#include <bits/stdc++.h>
using namespace std;
int n, a, b;
int arr[11];
int minn = INT_MAX; //最少攻击次数
vector<int> tmp, ans; //临时攻击日志,最优攻击日志
void dfs(int cur, int sum){ //攻击位置,总的攻击次数
if(sum >= minn) return; //剪枝
if(cur == n) {minn = sum; ans = tmp; return;}
for(int i=0; i<=16; i++){
if(arr[cur-1]-i*b>=0) continue;
if(cur==n-1 && (arr[cur]-i*a>=0 || arr[cur+1]-i*b>=0)) continue;
arr[cur] -= i*a, arr[cur-1]-=i*b, arr[cur+1]-=i*b; //打cur位置i次
for(int j=0; j<i; j++) tmp.push_back(cur); //储存
dfs(cur+1, sum+i);
arr[cur] += i*a, arr[cur-1]+=i*b, arr[cur+1]+=i*b; //回溯
for(int j=0; j<i; j++) tmp.pop_back();
}
}
int main(){
cin >> n >> a >> b;
for(int i=1; i<=n; i++) cin >> arr[i];
dfs(2, 0);
cout << minn << '\n';
for(int i : ans) cout << i << ' ';
}
-------------------------------------------------------------------------------------------------------------------------
补充:dp法的代码(是别的题解上的)
设 f[i][j][k] 表示到考虑第 i 个人,前 i-1 个人已经全被打死,其中第 i-1 个人受到了 j 个火球,第 i 个人受到了 k 个火球的最小使用火球数量。
#include <bits/stdc++.h>
using namespace std;
int f[15][20][20],n,hp[15],a,b,ans=2147483647,fr[20][20][20];
int main(){
scanf("%d%d%d",&n,&a,&b);
for(int i=1;i<=n;i++)
scanf("%d",&hp[i]);
memset(f,63,sizeof(f)); //memset为inf(次数不可能超过63)
for(int i=(hp[1]/b+1);i<=16;i++)
f[2][0][i]=i; //初始化,一开始只打了第二个人(并且注意必须打死第一个才能初始化)
for(int i=3;i<=n;i++) //i-1表示中间的人
for(int j=0;j<=16;j++) //左边打的次数
for(int k=0;k<=16;k++) //中间打的次数
for(int l=0;l<=16;l++) //右边打的次数
if((j+l)*b+k*a>hp[i-1]){ //中间的人能打死
if(f[i][k][l]>f[i-1][j][k]+l){ //f[i-1][j][k]+l表示打死前i-1个人总共需要的攻击次数,把它的最小值存到f[i][j][k]
f[i][k][l]=f[i-1][j][k]+l;
fr[i][k][l]=j; //存储前一个人被打次数
}
}
int rec=2147483647,ans=2147483647,p1,p2;
for(int i=0;i<=16;i++){
for(int j=0;j<=16;j++){
int now=hp[n-1]-i*b-j*a>=0?(hp[n-1]-i*b-j*a)/a+1:0;
if(j*b<=hp[n])now=(hp[n]-b*j)/b+1;
if(f[n-1][i][j]+now<ans){
ans=now+f[n-1][i][j];
rec=now;
p1=i;
p2=j;
}
}
}
printf("%d\n",ans);
for(int i=1;i<=rec;i++)
printf("%d ",n-1);
int now=n-1,rp1,rp2;
while((now-1)){
rp1=p1,rp2=p2;
p1=fr[now][rp1][rp2];
p2=rp1;
for(int i=1;i<=rp2;i++)
printf("%d ",now);
now--;
}
printf("\n");
return 0;
}