51nod 1489 蜥蜴和地下室(dfs or dp)

題目來源: CodeForces
基準時間限制:1 秒 空間限制:131072 KB 分值: 10 難度:2級算法題
 收藏
 關注

哈利喜歡玩角色扮演的電腦遊戲《蜥蜴和地下室》。此時,他正在扮演一個魔術師。在最後一關,他必須和一排的弓箭手戰鬥。他唯一能消滅他們的辦法是一個火球咒語。如果哈利用他的火球咒語攻擊第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 2
Output示例
3



dfs:


代碼如下:


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 12;
const int INF = 0x3f3f3f;
int h[maxn];
int n,a,b,ans,Min;

void dfs(int x,int res)
{
	if(x==n)
	{
		Min=min(Min,res);
		return ;
	}
	if(h[x-1]<0)
		dfs(x+1,res);
	int cnt=0;
	if(h[x-1]>=0)
	{
		cnt=h[x-1]/b+1;
		h[x-1]-=cnt*b;
		h[x]-=cnt*a;
		h[x+1]-=cnt*b;
		dfs(x+1,res+cnt);
		h[x-1]+=cnt*b;
		h[x]+=cnt*a;
		h[x+1]+=cnt*b;
	}
	int num=h[x]/a+1;
	if(h[x]>=0 && cnt<num)//當消滅x-1位置的次數可以在cnt和num之間時,暴搜找到最合適的次數 
	{
		for(int i=cnt+1;i<=num;++i)
		{
			h[x-1]-=b*i;
			h[x]-=a*i;
			h[x+1]-=b*i;
			dfs(x+1,res+i);
			h[x-1]+=b*i;
			h[x]+=a*i;
			h[x+1]+=b*i;
		}
	}
	return ;
}

int main()
{
	while(scanf("%d%d%d",&n,&a,&b)!=EOF)
	{
		ans=0; Min=INF;
		for(int i=1;i<=n;++i)
			scanf("%d",&h[i]);
		int cnt=h[1]/b+1;//先消滅第1個和最後一個 
		ans+=cnt;
		h[1]-=b*cnt;
		h[2]-=a*cnt;
		h[3]-=b*cnt;
		if(h[n]>=0)
		{
			cnt=h[n]/b+1;
			ans+=cnt;
			h[n]-=b*cnt;
			h[n-1]-=a*cnt;
			h[n-2]-=b*cnt;
		}
		dfs(2,0);
		if(Min==INF)
			Min=0;
		printf("%d\n",ans+Min);
	}
	return 0;
} 



dp


代碼如下:


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f;
int h[12];
int dp[12][18][18][18]; //表示在x位置時,x-1,x,x+1位置的生命值分別爲i,j,k時候的最小攻擊次數 
int main()
{
	int n,a,b;
	while(scanf("%d%d%d",&n,&a,&b)!=EOF)
	{
		for(int i=1;i<=n;++i){
			scanf("%d",&h[i]);
			h[i]++;//保證值爲0的時候就被消滅了 
		}
		for(int x=0;x<12;++x)
			for(int i=0;i<=16;++i)//注意初始化,i<16會WA 
				for(int j=0;j<=16;++j)
					for(int k=0;k<=16;++k)
						dp[x][i][j][k]=INF;
		dp[1][0][h[1]][h[2]]=dp[2][h[1]][h[2]][h[3]]=0;
		for(int x=2;x<n;++x)
			for(int i=h[x-1];i>=0;--i)
				for(int j=h[x];j>=0;--j)
					for(int k=h[x+1];k>=0;--k)
					{
						int ii = max(0,i-b);
						int jj = max(0,j-a);
						int kk = max(0,k-b);
						dp[x][ii][jj][kk] = min(dp[x][ii][jj][kk], dp[x][i][j][k]+1);
						if(i==0)
							dp[x+1][j][k][h[x+2]] = min(dp[x+1][j][k][h[x+2]], dp[x][i][j][k]);//可以攻擊x+1位置,消滅x位置的敵人 
						if(ii==0)
							dp[x+1][jj][kk][h[x+2]] = min(dp[x+1][jj][kk][h[x+2]], dp[x][i][j][k]+1);//保證第x-1位置敵人被消滅才能進入下一步	
					}
		printf("%d\n",dp[n][0][0][0]);	
	}
	return 0;
}


發佈了643 篇原創文章 · 獲贊 225 · 訪問量 50萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章