【蓝桥杯】 2018年决赛C/C++B组 #2 激光样式(动态规划、DFS)—— 酱懵静

2018决赛真题C/C++B组 激光样式

问题描述
x星球的盛大节日为增加气氛,用30台机光器一字排开,向太空中打出光柱。
安装调试的时候才发现,不知什么原因,相邻的两台激光器不能同时打开!
国王很想知道,在目前这种bug存在的情况下,一共能打出多少种激光效果?

显然,如果只有3台机器,一共可以成5种样式,即:
全都关上(sorry, 此时无声胜有声,这也算一种)
开一台,共3种
开两台,只1种

30台就不好算了,国王只好请你帮忙了。
要求提交一个整数,表示30台激光器能形成的样式种数。
注意,只提交一个整数,不要填写任何多余的内容。



---分割线---



思路一: DP
状态转移方程:dp[i] = dp[i - 1] + dp[i - 2],dp[i]表示一共有i展灯时的样式种数
当第i展灯亮,则i-1处的灯不能亮,此时dp[i] = dp[i - 2]
当第i展灯熄灭,则i-1处的灯随意亮暗都可以,此时dp[i] = dp[i - 1]
由于第i展灯有两种状态,于是推出dp[i] = dp[i - 1] + dp[i - 2]

下面直接给出完整代码:

#include<iostream>
using namespace std;
int dp[31];
int dfs(int n)
{
	if(n<3) return dp[n];
	return dfs(n-1)+dfs(n-2);
}
int main()
{
	dp[0]=0;	//没有灯,无方案
	dp[1]=2;	//一盏灯,只有开或者关两种方案
	dp[2]=3;	//两盏灯,最多只能同时开1盏灯,那么就只有不开、开第一盏灯、开第二盏灯共三种情况 
	cout<<dfs(30)<<endl;
	return 0;
 }


---分割线---



思路二:DFS一直向后搜索
下面直接给出完整代码:

#include<iostream>
using namespace std;
int sum;
void dfs(int n,bool flag)		//两个参数,分别代表当前灯的序号和当前灯是开还是关 
{
	if(n==30){
		sum++;
		return;
	}
	if(flag==true) dfs(n+1,false);//如果当前灯是开的,那么相邻的灯必须关 
	else{
		dfs(n+1,true);			//如果当前灯是关的的,那么相邻的灯可以开 
		dfs(n+1,false); 		//也可以关 
	}
}
int main()
{
	dfs(0,false);				//注意这里不能是dfs(1,false)或dfs(0,true),这样的意思是第一盏灯只能关不能开 
	cout<<sum<<endl;
	return 0;
 }



注:本题的答案为2178309
发布了30 篇原创文章 · 获赞 67 · 访问量 3042

猜你喜欢

转载自blog.csdn.net/the_ZED/article/details/100808058