蓝桥杯 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
上一篇: 寻路