ACM/ICPC 之 DFS范例(ZOJ2412-ZOJ1008)
通过几道例题简单阐述一下DFS的相关题型
ZOJ2412-Farm Irrigation
直观的DFS题型,稍加变化,记录好四个方向上的通路就能够做出来
题目和接水管类似,问最少要灌溉几次,即求解最少有多少个连通子图。
//和接水管游戏类似,将相应水管通路标记清晰即可
//Time:0Ms Memory:270K
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define MAX 55
#define OPPOSITE(x) ((x + 2) % 4) //x的相反位置
#define MAP(x,y) (map[x][y] - 'A') //水管序列
int row, col;
char map[MAX][MAX];
bool v[MAX][MAX];
int mov[][] = { {, }, {, }, {, -}, {-, } }; //东南西北
bool face[][] = { //face[i][j] : 在i方向上第j个水管是否有通路
{ ,,,,,,,,,, }, //东
{ ,,,,,,,,,, }, //南
{ ,,,,,,,,,, }, //西
{ ,,,,,,,,,, } //北
};
void dfs(int x,int y)
{
v[x][y] = true;
for (int i = ; i < ; i++)
{
int tx = x + mov[i][];
int ty = y + mov[i][];
if (face[i][MAP(x,y)] && tx >= && tx < row && ty >= && ty < col) //该水管相应对接方向有通路
{
if (!v[tx][ty] && face[OPPOSITE(i)][MAP(tx,ty)]) //对接水管相应方向有通路
dfs(tx, ty);
}
}
}
int main()
{
while (scanf("%d%d", &row, &col), row != - && col != -)
{
memset(v, false, sizeof(v));
for (int i = ; i < row; i++)
scanf("%s", map[i]);
int times = ;
for (int i = ; i < row; i++)
for (int j = ; j < col; j++)
{
if (!v[i][j]) {
times++;
dfs(i, j);
}
}
printf("%d\n", times);
}
return ;
}
ZOJ1008-Gnome Tetravex
看起来不像个搜索题,初看可能会以为需要枚举之类的,但是题中方块的各状态需要记录,在匹配失败时需要回退,因此是一道DFS题型。
大致的解题思路就是先枚举0行0列的方块,再依据此方块固定下一个方块,以此类推,出现不能匹配时回退。
虽然规模最大只有5,但是总方块数25个在DFS中也不可小觑,如果用纯DFS来做,时间度最坏可以达到O((n^2)!),因此剪枝或其他优化是必须的(只要数据不够水),我在超时后看了很多博客的解题报告(想不到了= =),就该题数据而言最好的优化方法是去重,即将相同方块合在一起,以减少DFS的分支数,但是我总觉得这么做挺奇怪的。。。虽然在大数据下,此题去重很有效果(数字在0-9,因此方块重复概率 < 1/2500),但是此题拿小数据故意出多组重复方块,不得不让人怀疑其心不善...
另外的剪枝方法,也有很多比较有效,但对此题没有太大帮助。
例如:记录各方向上各数字的个数,在匹配时动态增删,如果已经固定的方块需要的对应数字的数量缺失,那么就可以直接回退,剪枝效果在少量随机数据情况下比较好。
//去重就不会超时了,但这个优化实在是...让人感到很意外
//Time:2100ms Memory:272K
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std; #define MAX 28 int n, m;
int sq[MAX][]; //上右下左
int board[MAX]; //棋盘上对应位置的square
int v[MAX]; //记录同类sq未被使用的数量 bool dfs(int num)
{
if (num == n*n)
return true;
//找出可以充当第num个方块的i方块
for (int i = ; i < m; i++)
{
if (!v[i]) continue; //没有未固定方块
if (num % n && sq[i][] != sq[board[num - ]][]) continue; //非第一列+不匹配
if (num / n && sq[i][] != sq[board[num - n]][]) continue; //非第一行+不匹配 v[i]--;
board[num] = i;
if (dfs(num + )) return true;
else v[i] ++;
}
return false;
} int main()
{
int t = ;
while (scanf("%d", &n), n)
{
if (t) printf("\n"); memset(v, , sizeof(v));
memset(board, , sizeof(board));
m = ;
for (int i = ; i < n*n; i++)
{
int u, r, d, l;
scanf("%d%d%d%d", &u, &r, &d, &l);
//查重
bool flag = false;
for (int j = ; j < m; j++)
{
if (u == sq[j][] && r == sq[j][] && d == sq[j][] && l == sq[j][])
{
v[j]++;
flag = true;
break;
}
}
if (!flag) {
sq[m][] = u; sq[m][] = r; sq[m][] = d; sq[m][] = l;
v[m++] ++;
}
} if (dfs()) printf("Game %d: Possible\n", ++t);
else printf("Game %d: Impossible\n", ++t);
} return ;
}
ACM/ICPC 之 DFS范例(ZOJ2412-ZOJ1008)的更多相关文章
- ACM/ICPC 之 DFS+SPFA-贪心+最短路(POJ2679)
//POJ2679 //DFS+SPFA+邻接表 //只能走每个点费用最小的边,相同则需保证距离最短 //求最小费用及最短距离 //Time:47Ms Memory:900K #include< ...
- ACM/ICPC 之 DFS求解欧拉通路路径(POJ2337)
判断是欧拉通路后,DFS简单剪枝求解字典序最小的欧拉通路路径 //Time:16Ms Memory:228K #include<iostream> #include<cstring& ...
- ACM/ICPC 之 DFS求解欧拉回路+打表(POJ1392)
本题可以通过全部n位二进制数作点,而后可按照某点A的末位数与某点B的首位数相等来建立A->B有向边,以此构图,改有向图则是一个有向欧拉回路,以下我利用DFS暴力求解该欧拉回路得到的字典序最小的路 ...
- ACM/ICPC 之 Floyd范例两道(POJ2570-POJ2263)
两道以Floyd算法为解法的范例,第二题如果数据量较大,须采用其他解法 POJ2570-Fiber Network //经典的传递闭包问题,由于只有26个公司可以采用二进制存储 //Time:141M ...
- ACM/ICPC 之 Prim范例(ZOJ1586-POJ1789(ZOJ2158))
两道Prim解法范例题型,简单的裸Prim,且两题相较以边为重心的Kruskal解法而言更适合以点为重心扩展的Prim解法. ZOJ1586-QS Network 题意:见Code 题解:直接的MST ...
- ACM/ICPC 之 Kruskal范例(ZOJ1203-POJ1861(ZOJ1542))
两道最小生成树范例,Kruskal解法-以边为主体扩展最小生成树,需要利用并查集. ZOJ1203-Swordfish 题意:求n个给定平面坐标的城市中的一条平面距离上的最短路长(保留两位小数) 题解 ...
- ACM/ICPC 之 SPFA范例两道(POJ3268-POJ3259)
两道以SPFA算法求解的最短路问题,比较水,第二题需要掌握如何判断负权值回路. POJ3268-Silver Cow Party //计算正逆最短路径之和的最大值 //Time:32Ms Memory ...
- ACM/ICPC 之 BFS范例(ZOJ2913-ZOJ1136(POJ1465))
通过几道经典BFS例题阐述BFS思路 ZOJ2913-Bus Pass 题意:找一个center区域,使得center到所有公交线路最短,有等距的center则输出id最小的. 题解:经典的BFS,由 ...
- hduoj 4707 Pet 2013 ACM/ICPC Asia Regional Online —— Warmup
http://acm.hdu.edu.cn/showproblem.php?pid=4707 Pet Time Limit: 4000/2000 MS (Java/Others) Memory ...
随机推荐
- linux下设置进程优先级方法!
Linux系统下提升进程优先级的办法 Linux系统进程的优先级取值:-20 到 19,数越大优先级越低. 可以通过top命令来查看,NI那一列. 改变进程的优先级的方法有两种: www ...
- 今天是JQ 的slideUp 和 slideDown 的点击事件
先贴代码,再讲详细事件 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> & ...
- Linux关于添加硬盘的那些事儿:笔记
添加新硬盘:http://note.youdao.com/share/?id=8cf27602cdce36e1d4160f00e9004b00&type=note 关于添加硬盘的那些事儿: ...
- 2015年12月03日 GitHub入门学习(五)Markdown语法简介
Markdown一种标记语言,语法简洁,不像Word或Pages有大量排版.字体设置.常用的标记符号不超过十个.被大量写作爱好者.撰稿人.作家所青睐. 一.Markdown的优点 专注你的文字内容而不 ...
- jquery Ajax跨域调用WebServices方法
由于公司需要开发一个手机页面,想提供给同事直接在手机上可以查询SAP资料.数据需要使用js调用webserver来获取. 因为初次使用Jquery调用Webserver,所以期间并不顺利.测试调用We ...
- LUXURY15
A - Guess Your Way Out! Time Limit:1000MS Memory Limit:262144KB 64bit IO Format:%I64d & ...
- bug--java访问hdfs (Server IPC version 9 cannot communicate with client version 4 错误)
1. 今天想做一个hdfs的java工具类,但是在连接hdfs的时候,报如下错误: Exception in thread "main" org.apache.hadoop.ipc ...
- iOS8无法弹出本地通知?
最近在看<iOS编程(第4版)>(就是Big Nerd Ranch用的那本教材).这本书写的不错,推荐一下,写的很细致,循序渐进,不能不赞一下外国人写书的思路,确实跟国人不同.之前学And ...
- 网络编程2-UDP编程(DatagramSocket)
1.传输层有两个协议,一个是tcp协议,另一个是udp协议,tcp协议通过socket编程.udp通过数据报编程. UDP协议: (1)将数据.源地址.目的地址 封装成数据包,不需要建立链接 (2)每 ...
- c#常用的Datable转换为json,以及json转换为DataTable操作方法
#region DataTable 转换为Json字符串实例方法 /// <summary> /// GetClassTypeJosn 的摘要说明 /// </summary> ...