2013年:第39级台阶
2014年:李白打酒,地宫取宝
2015年:牌型种数
2016年:方格填数,剪邮票
2018年:全球变暖
2019年:迷宫
2020年:走方格,七段码
2022年模拟赛:2021变1的最短操作数
2022年第一次模拟赛:15级台阶
2022年国赛:扩散
小明刚刚看完电影《第39级台阶》,离开电影院的时候,他数了数礼堂前的台阶数,恰好是39级!
站在台阶前,他突然又想着一个问题:
如果我每一步只能迈上1个或2个台阶。先迈左脚,然后左右交替,最后一步是迈右脚,也就是说一共要走偶数步。那么,上完39级台阶,有多少种不同的上法呢?
请你利用计算机的优势,帮助小明寻找答案。
注意我们用的是dfs的思想,而非递归的思想(递归太容易绕进去了,博主也深受其害^^)
从地面开始向上走,有两种走法,上一层和上两层
只要我当前的台阶数不超过39,就可以继续深搜,否则的话,没必要继续下去
#include
using namespace std;
int ans;
void dfs(int step,int n){
if(n > 39){
return;
}
if(step%2==0 && n==39){
ans++;
return;
}
dfs(step+1,n+1);
dfs(step+1,n+2);
}
int main(){
dfs(0,0);
cout << ans;
return 0;
}
话说大诗人李白,一生好饮。幸好他从不开车。
一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:
无事街上走,提壶去打酒。 逢店加一倍,遇花喝一斗。
这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。
请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。
从家门口开始走,有两种可能,遇到店和遇到花
只要李白遇到店不超过5次,遇到花不超过9次,最后一次已确定,就可以继续深搜
#include
using namespace std;
int ans;
void dfs(int dian,int hua,int jiu){
if(dian > 5 || hua > 9){
return;
}
if(dian == 5 && hua == 9 && jiu == 1){
ans++;
return;
}
dfs(dian+1,hua,jiu*2);
dfs(dian,hua+1,jiu-1);
}
int main(){
dfs(0,0,2);
cout << ans;
return 0;
}
题目描述
X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。
地宫的入口在左上角,出口在右下角。
小明被带到地宫的入口,国王要求他只能向右或向下行走。
走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。
当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。
请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。数据格式
输入一行3个整数,用空格分开:n m k (1<=n,m<=50, 1<=k<=12)
接下来有 n 行数据,每行有 m 个整数 Ci (0<=Ci<=12)代表这个格子上的宝物的价值
要求输出一个整数,表示正好取k个宝贝的行动方案数。该数字可能很大,输出它对 1000000007 取模的结果。
例如,输入:
2 2 2
1 2
2 1
程序应该输出:
2
再例如,输入:
2 3 2
1 2 3
2 1 5
程序应该输出:
14
1.有三个参数,一个是坐标,一个是目前收集的宝物数目,一个是目前手里宝物中的最大价值
2.当(x,y)处的宝物的价值比我手里的最大价值大时,且我要拿,这是一种情况;剩下的就是另一种情况,虽然它比我手中的大但我不拿或我不能拿
3.当我到了终点,这时终点还没判断,终点需要单独判断,如果我已经拿了k件或者我拿了k-1件但终点的宝物价值比我手中的宝物价值大,我可以拿,也是k件
4.利用记忆化搜索简化时间复杂度,这里要注意因为我MaxV的初值设的是-1,而数组的下标不能有负数,所以我要加个偏移量1
#include
#include
using namespace std;
const int N = 60;
const long long MOD = 1e9+7;
int n,m,k;
int v[N][N];
long long mer[N][N][15][15];
long long dfs(int x,int y,int cnt,int MaxV){
if(x > n-1 || y > m-1 || cnt > k){
return 0;
}
if(x == n-1 && y == m-1){
if(cnt == k || (cnt == k-1 && v[x][y] > MaxV)){
return 1;
}
}
if(mer[x][y][cnt][MaxV+1] != -1){
return mer[x][y][cnt][MaxV+1];
}
long long ans = 0;
if(v[x][y] > MaxV){
ans += dfs(x + 1, y, cnt + 1, v[x][y]) + dfs(x, y + 1, cnt + 1, v[x][y]);
}
ans += dfs(x + 1, y, cnt, MaxV) + dfs(x, y + 1,cnt, MaxV);
return mer[x][y][cnt][MaxV+1] = ans%MOD;
}
int main(){
cin >> n >> m >> k;
for(int i = 0;i < n;i++){
for(int j = 0;j < m;j++){
cin >> v[i][j];
}
}
memset(mer,-1,sizeof(mer));
cout << dfs(0,0,0,-1);
return 0;
}
小明被劫持到X赌城,被迫与其他3人玩牌。 一副扑克牌(去掉大小王牌,共52张),均匀发给4个人,每个人13张。 这时,小明脑子里突然冒出一个问题: 如果不考虑花色,只考虑点数,也不考虑自己得到的牌的先后顺序,自己手里能拿到的初始牌型组合一共有多少种呢?
我从第1种牌开始走,选i张(0<=i<=4),再去下一种牌的面前……,将第一种牌当成迷宫的入口,最后一种牌当成是迷宫的出口,到了迷宫的出口,如果此时手中的牌刚好是13张,就是一个方案
#include
using namespace std;
int ans;
void dfs(int cnt,int sum){//cnt代表我走到第几点处了,sum表示我已经拿了几张牌了
if(cnt &