51Nod-1489 蜥蜴和地下室(暴力DFS)
阿新 • • 發佈:2018-12-24
Input
哈利喜歡玩角色扮演的電腦遊戲《蜥蜴和地下室》。此時,他正在扮演一個魔術師。在最後一關,他必須和一排的弓箭手戰鬥。他唯一能消滅他們的辦法是一個火球咒語。如果哈利用他的火球咒語攻擊第i個弓箭手(他們從左到右標記),這個弓箭手會失去a點生命值。同時,這個咒語使與第i個弓箭手左右相鄰的弓箭手(如果存在)分別失去b(1 ≤ b < a ≤ 10)點生命值。
因為兩個端點的弓箭手(即標記為1和n的弓箭手)與你相隔較遠,所以火球不能直接攻擊他們。但是哈利能用他的火球攻擊其他任何弓箭手。
每個弓箭手的生命值都已知。當一個弓箭手的生命值小於0時,這個弓箭手會死亡。請求出哈利殺死所有的敵人所需使用的最少的火球數。
如果弓箭手已經死亡,哈利仍舊可以將他的火球扔向這個弓箭手。
Input
第一行包含3個整數 n, a, b (3 ≤ n ≤ 10; 1 ≤ b < a ≤ 10),第二行包含n個整數——h1,h2,...,hn (1 ≤ hi ≤ 15), hi 是第i個弓箭手所擁有的生命力。Output
以一行輸出t——所需要的最少的火球數。Input示例
3 2 1 2 2 2Output示例
3思路:每次從第一個血量大於等於0的弓箭手開始,在dfs之前先把頭和尾打爆,並且儘量不直接打爆 ,只有這樣才能保證用的火球術最少,剩下直接dfs了。N很小,所以可以無腦暴力, 程式碼裡的註釋寫的很清楚,所以這裡不再過多解釋。。(網上有DP解法,只怪我太弱,不會用)
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<algorithm> #include<limits.h> #include<queue> #include<stack> #include<vector> #include<math.h> #include<map> using namespace std; #define maxn 105 #define inf 0xfffffff typedef long long ll; ll s[maxn],n,a,b,ans=inf,sum; void dfs(ll x,ll num)//x表示當前弓箭手,num表示當前釋放火球術的次數 { if(x==n) { ans=min(ans,num); return; } if(s[x-1]<0) dfs(x+1,num); ll t=0; if(s[x-1]>=0) { t=s[x-1]/b+1; num+=t; s[x-1]-=t*b; s[x]-=t*a; s[x+1]-=t*b; dfs(x+1,num); num-=t; s[x-1]+=t*b; s[x]+=t*a; s[x+1]+=t*b; } ll t1=s[x]/a+1; if(s[x]>=0 && t1>t)//假如打爆x-1後x還活著,則說明x的血量大於x-1, //因此要打爆x,此時打爆x有兩種方法,就是直接打爆和通過 //打爆x+1來打爆x { for(int i=t+1;i<=t1;i++) { num+=i; s[x-1]-=i*b; s[x]-=i*a; s[x+1]-=i*b; dfs(x+1,num); num-=i; s[x-1]+=i*b; s[x]+=i*a; s[x+1]+=i*b; } } return ; } int main() { ll i,j; memset(s,0,sizeof(s)); scanf("%lld%lld%lld",&n,&a,&b); for(i=1;i<=n;i++) scanf("%lld",&s[i]); ll x=s[1]/b+1;//先把頭和尾打爆 sum+=x; s[1]-=x*b; s[2]-=x*a; s[3]-=x*b; if(s[n]>=0) { x=s[n]/b+1; sum+=x; s[n]-=x*b; s[n-1]-=x*a; s[n-2]-=x*b; } dfs(2,0); if(ans==inf)ans=0; printf("%lld\n",sum+ans); }