老头怎么打边惩程咬金?
一直对dfs这一块比较懵(其实递归也挺懵的),所以找机会总结一下dfs和一些能用到的模版,勿喷
什么是dfs呢?
DFS环球免税购,荟萃逾700个全球知名品牌,涵盖时装配饰,美妆香水,腕表珠宝,葡萄酒和烈酒,美食及礼品。官方正品保证,乐享免税价格。DFS旗下澳门T广场,限时美妆惊喜连连,更有电子消费卡等多重优惠奖赏。成为T贵宾,更可尊享DFS独家礼遇与会员积分!
咳咳,对不起,搞错了,再来。
深度优先搜索属于图算法的一种,英文缩写为DFS即Depth First Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次.
举例说明之:下图是一个无向图,如果我们从A点发起深度优先搜索(以下的访问次序并不是唯一的,第二个点既可以是B也可以是C,D),则我们可能得到如下的一个访问过程:A->B->E(没有路了!回溯到A)->C->F->H->G->D(没有路,最终回溯到A,A也没有未访问的相邻节点,本次搜索结束).
(以上内容来源于百度百科)
算法这个东西知道是什么东西就行了,主要还是得由题说事,那么——
首先就是最经典的全排列问题:
1、全排列问题
【问题描述】 输出自然数 1 到 n 所有不重复的排列,即 n 的全排列,要求所产生的任一数字序列中不允许出现重复的 数字。 【输入格式】 n(1≤n≤9)
【输出格式】 由 1~n 组成的所有不重复的数字序列,每行一个序列。
可以发现,这就是一个典型的dfs,我们可以设置一个judge数组,用来记录当前的数有没有被取过,然后搜就完了,这个比较简单
#include<cstdio>
using namespace std;
int n,r,tot = 0;
int ans[1001] = { },judge[1001] = { };
void dfs(int x){if(x > n){for(int i = 1;i <= n; i++){printf("%5d" ,ans[i]);}printf("\n");return;}for(int i = 1;i <= n; i++){if(judge[i] == 0){judge[i] = 1;ans[x] = i;dfs(x + 1);judge[i] = 0;}}return;
}
int main()
{scanf("%d" ,&n);dfs(1);return 0;
}
还有一种版本的全排列(其实是组合的输出):
【问题描述】
排列与组合是常用的数学方法,其中组合就是从 n 个元素中抽出 r 个元素(不分顺序且 r<=n),我们 可以简单地将 n 个元素理解为自然数 1,2,…,n,从中任取 r 个数。
现要求你用递归的方法输出所有组合。
例如 n=5,r=3,所有组合为:
l 2 3 l 2 4 1 2 5 l 3 4 l 3 5 1 4 5 2 3 4 2 3 5 2 4 5 3 4 5 【输入】
一行两个自然数 n、r(1<n<21,1<=r<=n)。 【输出】
所有的组合,每一个组合占一行且其中的元素按由小到大的顺序排列,每个元素占三个字符的位置,所 有的组合也按字典顺序。
这个其实跟全排列是类似的,只需要把标准全排列的输出条件改一下就行了,也比较简单,这俩我刚开始学的时候是死记硬背然后硬套用的,多用用才慢慢知道是怎么回事
#include<cstdio>
using namespace std;
int n,r,tot = 0;
int ans[1001] = { },judge[1001] = { };
void dfs(int x){if(x > r){for(int i = 1;i <= r; i++){printf("%d" ,ans[i]);}printf("\n");tot++;return;}for(int i = 1;i <= n; i++){if(judge[i] == 0){judge[i] = 1;ans[x] = i;dfs(x + 1);judge[i] = 0;}}return;
}
int main()
{scanf("%d %d" ,&n,&r);dfs(1);printf("%d" ,tot);return 0;
}
还有一道很经典的题,就是”臭名远扬“的八皇后:
N 皇后问题(queen.cpp) 【问题描述】 在 N*N 的棋盘上放置 N 个皇后(n<=10)而彼此不受攻击(即在棋盘的任一行,任一列和任一对角线上 不能放置 2 个皇后),编程求解所有的摆放方法。
(其实把8改成n是更具有普遍性的)
#include<cstdio>
using namespace std;
int tot = 0,n;
int a[100] = { },b[100] = { },he[100] = { },cha[100] = { },ans[100] = { };//二维数组容易乱,一位数组清晰一些
void print(){for(int j = 1;j <= n; j++){printf("%d " ,ans[j]);}printf("\n");
}
void dfs(int now,int x){if(now > n){tot++;if(tot <= 3) print();return;}for(int j = 1;j <= n; j++){if(b[j] == 0 && he[x + j] == 0 && cha[x - j + n] == 0){ //标记前后左右对角线b[j] = 1;he[x + j] = 1;cha[x - j + n] = 1;ans[now] = j;dfs(now + 1,x + 1);b[j] = 0;he[x + j] = 0;cha[x - j + n] = 0;}}
}
int main()
{scanf("%d" ,&n);dfs(1,1);printf("%d" ,tot);return 0;
}
还有一道模版题就是迷宫
迷宫问题(migong) 【问题描述】
设有一个 N*N(2<=N<10)方格的迷宫,入口和出口分别在左上角和右上角。迷宫格子中 分别放 0 和 1,0 表示可通,1 表示不能,入口和出口处肯定是 0。迷宫走的规则如下所示: 即从某点开始,有八个方向可走,前进方格中数字为 0 时表示可通过,为 1 时表示不可通过, 要另找路径。找出所有从入口(左上角)到出口(右上角)的路径(不能重复),输出路径总 数,如果无法到达,则输出 0。
这个肯定还是dfs(其实bfs也是可以的)
#include<cstdio>
using namespace std;
int place[10001][10001] = { },judge[10001][10001] = { };
int n,tot = 0;
void dfs(int x,int y){if(judge[x][y] == 1 || x < 1 || y < 1 || x > n || y > n) return;if(x == 1 && y == n){tot++;return;}judge[x][y] = 1;dfs(x,y + 1);dfs(x + 1,y + 1);dfs(x + 1,y);dfs(x,y - 1);dfs(x - 1,y + 1);dfs(x + 1,y - 1);dfs(x - 1,y);dfs(x - 1,y - 1);judge[x][y] = 0;
}
int main()
{scanf("%d" ,&n);for(int i = 1;i <= n; i++){for(int j = 1;j <= n; j++){scanf("%d" ,&place[i][j]);judge[i][j] = place[i][j];}}dfs(1,1);printf("%d" ,tot);return 0;
}
/*30 0 00 1 11 0 0*/
那么有了这几道模版题,有很多类型题就可以迎刃而解了,
设有n件工作分配给n个人。将工作i分配给第j个人所需的费用为c ij 。试设计一个算法,为每一个人都 分配一件不同的工作,并使总费用达到最小。 【编程任务】
设计一个算法,对于给定的工作费用,计算最佳工作分配方案,使总费用达到最小。 【输入格式】
第一行有1个正整数n (1≤n≤20)。接下来的n行,每行n个数,第i行表 示第i个人各项工作费用。
这道题其实就是一个八皇后,只不过把对角线的判定去掉就行了
#include<cstdio>
using namespace std;
int tot = 230081343,n;
int a[100] = { },b[100] = { },ans[100] = { },k = 0;
int h[10001][10001] = { };
void print(){k = 0;//≥ı ºªØ for(int i = 1;i <= n; i++){k = k + h[i][ans[i]];}if(k < tot) tot = k;
}
void dfs(int now,int x){if(now > n){print();return;}for(int j = 1;j <= n; j++){if(b[j] == 0){b[j] = 1;ans[now] = j;dfs(now + 1,x + 1);b[j] = 0;}}
}
int main()
{scanf("%d" ,&n);for(int i = 1;i <= n; i++){for(int j = 1;j <= n; j++){scanf("%d" ,&h[i][j]);}}dfs(1,1);printf("%d" ,tot);return 0;
}
/*34 2 52 3 63 4 5*/
而排列组合可以用来解决子集合问题等,其实用dfs解决这些问题归根结底就是暴搜,所以应该特别关注一下数据范围,然后想尽一切办法减少搜索次数,不然的话非常容易爆时间,严重的时候一半多的数据都过不去
我的dfs总结更新啦!以下是新的内容
海战
在峰会期间,武装部队得处于高度戒备。警察将监视每一条大街,军队将保卫建筑物,领空将布满了F-2003飞机。此外,巡洋船只和舰队将被派去保护海岸线。不幸的是因为种种原因,国防海军部仅有很少的几位军官能指挥大型海战。因此,他们考虑培养一些新的海军指挥官,他们选择了“海战”游戏来帮助学习。
在这个著名的游戏中,在一个方形的盘上放置了固定数量和形状的船只,每只船却不能碰到其它的船。在这个题中,我们仅考虑船是方形的,所有的船只都是由图形组成的方形。编写程序求出该棋盘上放置的船只的总数。
输入格式
输入文件头一行由用空格隔开的两个整数R和C组成,1<=R,C<=1000,这两个数分别表示游戏棋盘的行数和列数。接下来的R行每行包含C个字符,每个字符可以为“#”,也可为“.”,“#”表示船只的一部分,“.”表示水。
#include<cstdio>
#include<iostream>
using namespace std;
char s[10001][10001];
bool jd[10001][10001];
int r,c;
int tot = 0;
void dfs(int x,int y){if(jd[x][y] != 0 || x > r || y > c || x == 0 || y == 0 || s[x][y] != '#'){return;}if(jd[x][y] == 0 && s[x][y] == '#'){jd[x][y] = 1;dfs(x + 1,y);dfs(x - 1,y);dfs(x,y + 1);dfs(x,y - 1);}return;
}
int main(){scanf("%d %d" ,&r,&c);for(int i = 1;i <= r; i++){for(int j = 1;j <= c; j++){cin>>s[i][j];}}
// for(int i = 1;i <= r; i++){// for(int j = 1;j <= c; j++){// printf("%c" ,s[i][j]);
// }
// printf("\n");
// }for(int i = 1;i <= r; i++){for(int j = 1;j <= c; j++){int k = 0;if(s[i][j] == '#')k++;if(s[i + 1][j] == '#')k++;if(s[i][j + 1] == '#')k++;if(s[i + 1][j + 1] == '#')k++;if(k == 3){printf("Bad placement.");return 0;}}}for(int i = 1;i <= r; i++){for(int j = 1;j <= c; j++){if(s[i][j] == '#' && jd[i][j] == 0){// printf("%d %d\n",i,j);dfs(i,j);tot++;}}}printf("There are %d ships." ,tot);return 0;
}
这道题的dfs思路不同于以往,这道题是要依靠dfs把一条船清空,我们先判断它是否是不合理的摆放,如果不是的话从头开始枚举点dfs,当我们找到代表船的点,进入dfs,把这一整条船都清空,这样一来dfs的次数就是船的数量了
下面是一道类似的题:细胞数量
一矩形阵列由数字 0 到 9 组成,数字 1 到 9 代表细胞,细胞的定义为沿细胞数字上下左右若还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。
这道题还是跟刚才一样了,用dfs清空细胞,dfs的次数就是细胞数
#include<cstdio>
#include<cstring>
using namespace std;
int m,n;
int a[10001][10001] = { };
int dx[] = {1,0,-1,0},dy[] = {0,1,0,-1};
void dfs(int x,int y){if(x > n || y > m || x < 1 || y < 1 || a[x][y] == 0){return;}a[x][y] = 0;for(int i = 0;i < 4; i++){dfs(x + dx[i],y + dy[i]);dfs(x + dx[i],y + dy[i]);dfs(x + dx[i],y + dy[i]);dfs(x + dx[i],y + dy[i]);}
}
int main(){scanf("%d %d" ,&n,&m);for(int i = 1;i <= n; i++){for(int j = 1;j <= m; j++){scanf("%1d" ,&a[i][j]);}}int tot = 0;for(int i = 1;i <= n; i++){for(int j = 1;j <= m; j++){if(a[i][j] != 0){tot++;dfs(i,j);}}}printf("%d" ,tot);return 0;
}
由这两道题可见,dfs还是可以用的非常灵活的,我对dfs的理解和应用肯定也不是那么的厉害,所以还是需要继续通过刷题来提高啊QAQ
老头怎么打边惩程咬金?相关推荐
- 健身环爆打老头环!超高难度击败boss,宫崎英高估计也想不到,代码+硬件教程已开源...
晓查 萧箫 发自 凹非寺 量子位 | 公众号 QbitAI 7天销量破1000万的<艾尔登法环>,彻底火出圈了. 被玩家们亲切称为"老头环"的它,首发当日在线人数就在S ...
- 街头抓拍之一:酷似福克纳的老头
灯市口.一个酷似威廉·福克纳的老头,在街口专注地等着人行道的绿灯. 东华门小吃街.一个睡态可掬的小男孩. 故宫前广场.两个公然掰腕较力的汉子.
- 最优化课程笔记07——约束问题的非线性规划方法(重点:拉格朗日乘子法和惩罚函数法)
7.1 间接法:约束转化为无约束问题(含一个重点:拉格朗日乘子法) 当维数多的时候不适用 7.1.2拉格朗日乘子法(重点) 7.1.2.1 等式约束问题 7.1.2.2 不等式约束问题 7.1.3 惩 ...
- matlab 约束函数,【优化求解】MATLAB约束优化之惩罚函数法
一.算法原理 之前我们了解过的算法大部分都是无约束优化问题,其算法有:黄金分割法,牛顿法,拟牛顿法,共轭梯度法,单纯性法等.但在实际工程问题中,大多数优化问题都属于有约束优化问题.惩罚函数法就可以将约 ...
- 王者荣耀 兵线刷新时间计数器 || 程咬金 水晶断兵线时间
软件在百度网盘,链接:https://pan.baidu.com/s/1sp3_8JawMIU8DDX-npuVEw 密码:yhpw 这是一个用C#写的,在电脑上运行de小软件. 在看熊猫 ...
- 养狗养成小老头?宠物泪痕严重如何护理?
宠物泪痕护理 宠物泪痕的问题肯定大家都不陌生 两条黑红丑丑的痕迹像是两撇胡子 让原本可爱的毛孩子像一个邋遢的小老头 今天胖胖和大家分享 宠物泪痕护理! NO.1 宠物泪痕严重的原因 一.饮食不当: 这 ...
- 抖音一个老人和一个机器人歌曲_《抖音》多年以后有个可爱老头歌曲分享
小编最近在<抖音>里面听到了一首非常好听的歌曲,只不过歌名已经忘记了.而其中有一句歌词是:"多年以后有个可爱老头".不知道大家对于这一首歌有没有印象呢?接下来,小编就给 ...
- 《老头滚动条5》买屋 周详方案向导
<老头滚动条5>买屋 周详方案向导 1·地点[雪漫城Whiterun-风宅Breezehome]·购屋:5000·装饰费用:1800 2·地点[马卡斯城Markath-林德尔会堂Vlind ...
- 王海桑《爷爷是个老头》
爷爷是个老头 王海桑 打我记事开始,爷爷就是个老头 他那么老,好像从来不曾年轻过 他那么老,好像生来只为了做我的爷爷 可我从未认真想过他有一天会死 我总以为,一个人再老,总可以再活一年吧 然而有一天他 ...
最新文章
- 2020人工智能课程超级大列表:深度学习-强化学习-图神经网络-自然语言处理等...
- Xamarin.Forms单元控件Cell
- python调用r语言_【Python调用第三方R包】【环境变量设置】Python 通过rpy2调用 R语言...
- 工作195:解决key值不唯一的报错
- 手机modem 开发(2)---MTK modem的修改点
- bzu-java(五)
- Visual Studio 2015 前端开发工作流
- ETC passwd 用户和组管理
- Jira7.10.1在Windows环境下的安装和配置
- 企业分布式微服务云SpringCloud SpringBoot mybatis (八)消息总线(Spring Cloud Bus)
- 管道无损检测python_初用python-docx
- kubelet liveness probe源码简析
- 2018金山wps暑期招聘服务器端笔试题(第二批)
- 用UWP模仿网易云音乐的动画
- 大三Web课程设计——悬崖上的波妞(4页) HTML+CSS(可以很好的应付老师的作业)
- 解决摄像机被遮挡问题
- TeaTalk·Online 大数据+云原生,再度风云起
- Pandas中melt()的使用
- 4 NLP之数据平滑技术
- centos7无法读取移动硬盘