欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-21 18:01:36
...

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