1489 蜥蜴和地下室+bfs
阿新 • • 發佈:2018-11-17
題目連結:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1489
題目大意:輸入第一行包含3個整數 n, a, b
第二行輸入n只蜥蜴的生命值,你可以選擇編號為2~n的任意第i只蜥蜴進行火球術,對第i只蜥蜴造成a點傷害,對左右的蜥蜴造成b點傷害,當生命值<0時蜥蜴死亡(巨坑),但可以繼續攻擊,求殺死全部蜥蜴的最小攻擊次數。
n和hi的範圍都比較小,考慮dfs。
當是純dfs會爆,所以還要有策略的dfs。
因為這道題有點和poj那個熄滅燈泡有的像。必須找到一個狀態,再dfs。因為題目中說第1,n不能直接打。所以1,n只能通過打2,n-1消滅。然後從左到右打,消滅第i只有兩種方式。
一:打第i只,需要打(hi+a-1)/a下。
二:打第i+1只,需要打(hi+b-1)/b下。
但是這裡只考慮打打第i+1只,因為打第i-1只時,便是第一種打法。
開始考慮把第i只消滅,就消滅第i+1推導第n只。但是最後一隻要特殊考慮。因為a>b;直接打本身更快,然後提交有幾個樣例WA了。
後來發現考慮有點問題,因為上面說因為打第i-1只時,便是第一種打法。因為打第i-1只時只打了(h(i-1)+b-1)/b)可能是小於(hi+a-1)/a的,這樣打(h(i-1)+b-1)/b)~(hi+a-1)/a下第i-1只都會死亡,所以dfs打的次數。AC
#include<bits/stdc++.h> using namespace std; int s[20]; int min_s=0x7fffffff; int n, a, b; void dfs(int i, int ans) { if(i==n) { min_s=min(min_s, ans); return; } if(s[i]<=0) { dfs(i+1, ans); } int m1=0; if(s[i]>0)//情況二 { m1=(s[i]+b-1)/b; s[i]-=m1*b; s[i+1]-=m1*a; s[i+2]-=m1*b; dfs(i+1, ans+m1); s[i]+=m1*b; s[i+1]+=m1*a; s[i+2]+=m1*b; } int m2=(s[i+1]+a-1)/a; if(m2>m1) //(h(i-1)+b-1)/b小於(hi+a-1)/a { for(int j=m1+1;j<=m2;j++) { s[i]-=j*b; s[i+1]-=j*a; s[i+2]-=j*b; dfs(i+1, ans+j); s[i]+=j*b; s[i+1]+=j*a; s[i+2]+=j*b; } } } int main() { scanf("%d%d%d",&n,&a,&b); for(int i=1;i<=n;i++) { scanf("%d",&s[i]); s[i]++; } int m1=(s[1]+b-1)/b;//消滅第1只 s[1]=0; s[2]-=a*m1; s[3]-=b*m1; int m2=(s[n]+b-1)/b;//消滅第n只 m2=max(0, m2); s[n]=0; if(n-1>=0) s[n-1]-=a*m2; if(n-2>=0) s[n-2]-=b*m2; dfs(2, m1+m2); cout<<min_s<<endl; return 0; }