华师一附中OI组
标题:
DFS大楼
[打印本页]
作者:
admin
时间:
2018-5-10 17:39
标题:
DFS大楼
DFS是信息学奥赛的重要内容,学好DFS是进入中级选手的标记,DFS的题目主要涉及数学建模,状态标识,规则转换,程序优化等方面
1、入门题目
12345五个数字选出三个组成一个三位数,这样的三位数有多少个。 基本pmn
ABCDE五个字母组成的长度为三的字符串,有多少个 位置转换
AAABBCDE中选出3个字母组成字符串有多少个 有重排列
ABCDE中选出3个人去参加比赛,有多少种方法 组合的生成
练习题:
P1706 全排列问题
http://www.hsyit.cn/forum.php?mo ... 5875&extra=page%3D1
P1157 组合的输出
http://www.hsyit.cn/forum.php?mo ... 5874&extra=page%3D1
P1691 有重复元素的排列问题
http://www.hsyit.cn/forum.php?mo ... 5876&extra=page%3D1
P1036 选数
http://www.hsyit.cn/forum.php?mo ... 5881&extra=page%3D1
2、基本变形 包括选择约束,位置跳过,深度可变,极值记忆、剪枝等
123456789排成一排,相邻的两个数字之和为质数,有多少种方法,排成一个环呢 有约束条件的pmn
11223344八个数字排成一排,要求i和i之间隔i个位置,如何摆放? 位置上有约束
1*2的骨牌去覆盖4*4 的格子,有多少种方法 平面约束
1-9九个数字放在3*3的方格里,相邻的数字之和为质数,怎么放?所谓相邻,指左右上下的数字
m个物品在一定的约束条件下怎么选才能使总和最大 背包问题
100分成6个数的和
http://www.hsyit.cn/forum.php?mod=viewthread&tid=24
P2404 自然数的拆分问题
http://hsyit.cn/forum.php?mod=viewthread&tid=35927
P1049 装箱问题
http://hsyit.cn/forum.php?mod=viewthread&tid=36213
P1443 马的遍历
http://www.hsyit.cn/forum.php?mo ... 5886&extra=page%3D1
P1238 走迷宫
http://www.hsyit.cn/forum.php?mod=viewthread&tid=35919
P1060 开心的金明
http://www.hsyit.cn/forum.php?mo ... 5890&extra=page%3D1
P1123 取数游戏
http://www.hsyit.cn/forum.php?mo ... 5882&extra=page%3D1
2^n最少要算多少次乘法
http://www.hsyit.cn/forum.php?mod=viewthread&tid=3663&highlight=2
P1784 数独
http://www.hsyit.cn/forum.php?mo ... 5788&highlight=1784
P1019 单词接龙
http://www.hsyit.cn/forum.php?mod=viewthread&tid=35880
P1101 单词方阵
http://www.hsyit.cn/forum.php?mod=viewthread&tid=36006
P2819 图的m着色问题
http://www.hsyit.cn/forum.php?mod=viewthread&tid=36045
P1692 部落卫队
http://hsyit.cn/forum.php?mod=viewthread&tid=36396
3、技巧
P1473 零的数列 Zero Sum
http://www.hsyit.cn/forum.php?mod=viewthread&tid=35991
1-m之间那个数字的约数最多,若相同,输出最小的那个
http://www.hsyit.cn/forum.php?mod=viewthread&tid=35845
P1254 扇区填数
http://www.hsyit.cn/forum.php?mo ... 5884&extra=page%3D1
P1731 [NOI1999]生日蛋糕
http://www.hsyit.cn/forum.php?mo ... hlight=%C9%FA%C8%D5
智慧珠游戏
http://www.hsyit.cn/forum.php?mo ... 5879&extra=page%3D1
P1139 单向双轨道
http://www.hsyit.cn/forum.php?mod=viewthread&tid=35924
P1092 虫食算
http://www.hsyit.cn/forum.php?mod=viewthread&tid=36035
P1021 邮票面值设计
http://www.hsyit.cn/forum.php?mod=viewthread&tid=36036
P2668 斗地主
http://www.hsyit.cn/forum.php?mod=viewthread&tid=35889
IOI'94 汽车问题
http://www.hsyit.cn/forum.php?mod=viewthread&tid=36358
P3956 棋盘
http://hsyit.cn/forum.php?mod=viewthread&tid=36320
4、迭代加深的技术
埃及分数
http://www.hsyit.cn/forum.php?mod=viewthread&tid=35932
UVA1343 The Rotation Game
http://www.hsyit.cn/forum.php?mod=viewthread&tid=35933
P2324 [SCOI2005]骑士精神
http://www.hsyit.cn/forum.php?mod=viewthread&tid=36013
poj2870Light Up
http://www.hsyit.cn/forum.php?mod=viewthread&tid=35934
解集个数
http://www.hsyit.cn/forum.php?mod=viewthread&tid=36355
5、进阶
P1514 引水入城
http://hsyit.cn/forum.php?mod=viewthread&tid=36397
P1139 单向双轨道
http://www.hsyit.cn/forum.php?mod=viewthread&tid=35924
还是N皇后
http://www.hsyit.cn/forum.php?mod=viewthread&tid=35992
P1363 幻想迷宫
http://www.hsyit.cn/forum.php?mod=viewthread&tid=35987
加强版的数独
作者:
admin
时间:
2018-8-26 18:59
一个问题要是需要用DFS来解决的话,首先的考虑几个问题,以M个数字里面选N个为例,这个是最基本的:
1、待选的对象是谁。这里是M个数字
2、规则是什么样的,也就是for循环里面的那个k的变化情况,这里就是1到M,和上面一样,简化了嘛!
3、约束条件是什么,就是for循环里面的那个if,这里就是说选过的不能再选,所以需要一个bool数组;
4、终止条件是什么,就是进入函数的那个if,这里就是N个数字已经选完,开始选第N+1个数字,所以是i>=N+1
这四个问题都想清楚了,套格式就是程序。
作者:
admin
时间:
2019-10-25 15:34
简单的DFS一般有两种框架,我喜欢用第一种
void dfs(int i)
{
if (i>=N+1) /// 到达深度终点
pp() ///输出或者判断
else
for (int k=1; k<=M; k++) ///循环使用M条规则
if (b) ///若可行
{
a[i]=k; ///记录这个决策
B[x]=0; ///相应的约束条件变化
dfs(i+1); ///递归下一个
B[x]=1; ///还原相应的约束条件
}
}
复制代码
也有人把这个终点判断放在for循环里面,这似乎不是很要紧
viod dfs(int i)
{
for (int k=1; k<=M; k++) ///循环使用M条规则
if (b) ///若可行
{
a[i]=k; ///记录这个决策
B[x]=0; ///相应的约束条件变化
if (i<N) dfs(i+1); ///递归下一个
else pp();
B[x]=1; ///还原相应的约束条件
}
}
复制代码
作者:
admin
时间:
2019-10-25 15:53
一个问题要是需要用DFS来解决的话,首先的考虑几个问题,以M个数字里面选N个为例,这个是最基本的:
1、搜索的对象是谁。这里是N个位置上的数字,也就是说dfs(i)中i表示第i个位置,a(i)=k表示第i个位置上放的数字是k。
2、规则是什么样的,也就是for循环里面的那个k的变化情况,这里就是1到M,和上面一样,简化了嘛!
3、约束条件是什么,就是for循环里面的那个if,这里就是说选过的不能再选,所以需要一个bool数组;
4、终止条件是什么,就是进入函数的那个if,这里就是N个位置上的数字已经选完,开始选第N+1个位置,所以是i>=N+1
这四个问题都想清楚了,套格式就是程序。
再看一个难一点的间隔排列:假设有8个数字,11223344
1、搜索的对象是谁。这里是8个位置,每个位置上的数字,注意:不是4而是8。a(i)=k表示第i个位置上放数字k而不是数字i放在k位置上!!!!
2、规则是什么样的,也就是for循环里面的那个k的变化情况,这里就是1到4,也要注意!但是比上面那题多了一点,放过了的直接跳过去。所以多了一个if
3、约束条件是什么,就是for循环里面的那个if,这里就比较多了,1选过的不能再选,2要能保证两个数码都能放得下去。所以比较复杂。
4、终止条件是什么,就是进入函数的那个if,这里就是8个位置已经选完,所以是i>=9
对比下楼下的这两个程序
作者:
admin
时间:
2019-10-25 15:54
间隔排列:
#include <iostream>
using namespace std;
const int mm=18;
bool b[mm];
int a[mm*2];
int n=4;
void dfs(int i)
{
int j,k;
if (i>n*2) ///摆放完毕,输出
{
for(j=1; j<=n*2; j++) cout<<a[j]<<' ';
cout<<endl;
}
else if (a[i]>0) dfs(i+1); ///!!!这个格子已经被预先摆放了
for (k=1; k<=n; k++)
{
int x=i+k+1; ///计算那一个格子的位置
bool b1=(x<=2*n); ///不可以超出范围
bool b2=(a[x]==0);///不可以被占用
bool bb=b[k] && b1 && b2;
if (bb)
{
a[i]=a[x]=k;
b[k]=0;
dfs(i+1);
b[k]=1;
a[i]=a[x]=0;
}
}
}
int main()
{
for (int i=1; i<=n; i++) b[i]=1;
dfs(1);
return 0;
}
复制代码
作者:
admin
时间:
2019-10-25 15:56
标准的5选3
#include<iostream>
using namespace std;
const int mm=10;
int a[mm];/// 选出来的
int b[mm]; ///是否被选择
int m,n,j;
void pp()
{
for (int i=1; i<=n; i++) cout<<a[i]<<' ' ;
cout<<endl;
}
void dfs(int i)
{
if (i>n) pp();
else for (int j=1; j<=m; j++)
if (b[j])
{
a[i]=j;
b[j]=0;
dfs(i+1);
b[j]=1;
}
}
int main()
{
m=5,n=3;
b[1]=b[2]=b[3]=b[4]=b[5]=1;
dfs(1);
return 0;
}
复制代码
作者:
张溯源
时间:
2020-3-1 21:25
本帖最后由 张溯源 于 2020-3-1 21:27 编辑
孙老师果然真是牛逼
献上关于组合的代码:
#include<iostream>
#include<cstdio>
using namespace std;
int n,r;
int a[23];
bool b[23]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
void pr()
{
for(int i=1;i<=r;i++)
printf("%3d",a[i]);
cout<<endl;
}
void pmn(int i)
{
if(i>r)
pr();
else
{
for(int h=a[i-1]+1;h<=n;h++)
if(b[h]==1)
{
b[h]=0;
a[i]=h;
pmn(i+1);
b[h]=1;
}
}
}
int main()
{
cin>>n>>r;
pmn(1);
return 0;
}
复制代码
作者:
admin
时间:
2020-3-2 13:04
1657 选书值得一做
作者:
朱品屹
时间:
2020-8-5 09:36
admin 发表于 2020-3-2 13:04
1657 选书值得一做
#include<iostream>
using namespace std;
int a[50],ans=0,x,t1,t2;;
bool b[50],like[50][50];//like[i][j]表示第i个人喜欢第j本书。
void dfs(int i)
{
if(i>x) ans++;
else
{
for(int k=1;k<=x;k++)
{
if(b[k]&&like[i][k])//此书未选且第i个人喜欢这本书
{
a[i]=k; //a数组如果不用输出可以不要
b[k]=0;
dfs(i+1);
b[k]=1;
}
}
}
}
int main()
{
cin>>x;
if(x==0) cout<<0; //这里要特判一下
else
{
for(int i=1;i<=x;i++)
{
cin>>t1>>t2;
like[i][t1]=1;
like[i][t2]=1;
}
for(int i=1;i<=x;i++)
b[i]=1;
dfs(1);
cout<<ans;
}
return 0;
}
复制代码
欢迎光临 华师一附中OI组 (http://hsyit.cn/)
Powered by Discuz! X3.2