网站:CSUST 8月1日

先总结下,不得不说死的很惨,又是第三就不说了,一共7道题,AC了5道,但是有一个组三个人是做的个人赛,有两人AK了.......Orz,然后深搜还是大问题,宽搜倒是不急了。

而且,其中还有一题是水过去的。唉,不说了,好好看。╮(╯▽╰)╭

A    骑士历遍问题:给出m,n,指大小为m*n的棋盘,问骑士是否能遍历整个棋盘,要求把路径打出来,(要按字典序)A Knight's Journey   POJ 2488

网上找到了个很好地代码,解释很清晰:http://www.slyar.com/blog/poj-2488-c.html    (以下解释来自这里)

Slyar:说一下题目大意。给出一个国际棋盘的大小,判断马能否不重复的走过所有格,并记录下其中按字典序排列的第一种路径。

"马的遍历"是一道经典回溯题,当然还是DFS...这题有3个要密切注意的地方:

1、题目要求以"lexicographically"方式输出,也就是字典序...一开始没看懂这个词结果WA了N次...要以字典序输出路径,那么方向数组就要以特殊的顺序排列了...这样只要每次从dfs(1,1)开始搜索,第一个成功遍历的路径一定是以字典序排列...

2、国际象棋的棋盘,横行为字母,表示横行坐标的是y;纵行为数字,表示纵行的坐标是x...一开始又搞反了...

代码:16MS

 #include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
int map[][],x[],y[];
int d[][]={{-, -}, {-, }, {-, -}, {-, },{, -}, {, }, {, -}, {, }}; //字典序
int m,n,sign,step;
void dfs(int i,int j)
{
int a,b,k;
if(sign) //以历遍,跳出
return ;
step++;
x[step]=i; //当前位置
y[step]=j;
if(step==m*n) //步数=格子数
{
sign=;
return ;
}
map[i][j]=; //标记
for(k=;k<;k++)
{
b=j+d[k][]; //注意
a=i+d[k][];
if(map[a][b]== && a> && b> && a<=m && b<=n)
{
dfs(a,b);
step--; //不符合要求是回溯步数 }
}
map[i][j]=; //返回
}
int main()
{
int T,i,t=;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&m,&n);
t++;
memset(map,,sizeof(map));
step=;
sign=;
dfs(,);
printf("Scenario #%d:\n", t);
if(sign)
{
for(i=;i<=m*n;i++)
printf("%c%d",y[i]+,x[i]); //注意这里,先是y,再是x
printf("\n\n"); //要空一行
}
else printf("impossible\n\n"); //要空一行
}
return ;
}

B 大意是:找出最大的湖泊的格子数,只能上下左右,对角不算相连    Avoid The Lakes     POJ 3620

代码:      16ms  BFS

 #include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int d[][]={{,},{,},{,-},{-,}};
int map[][];
int m,n;
class A
{
public:
int a;
int b;
};
A q[];
void bfs()
{
A r,t;
int i,j,ans,k,maxn=;
for(j=;j<=m;j++) //扫描
for(k=;k<=n;k++)
{
if(map[j][k]==)
{
ans=;
int g=;
int h=;
map[j][k]=; //标记
q[g].a=j; //开始的位置
q[g].b=k;
g++;
while(h!=g)
{
r=q[h++];
for(i=;i<;i++)
{
t.a=r.a+d[i][];
t.b=r.b+d[i][];
if(t.a> && t.a<=m && t.b> && t.b<=n && map[t.a][t.b]==) //满足条件
{
q[g++]=t;
map[t.a][t.b]=; //标记
ans++;
}
}
}
if(maxn<ans) //找出最大值
maxn=ans;
}
}
cout<<maxn<<endl;
}
int main()
{
int i,j,k,x;
memset(map,,sizeof(map));
while(~scanf("%d%d%d",&m,&n,&x))
{
for(i=;i<x;i++)
{
scanf("%d%d",&j,&k);
map[j][k]=;
}
bfs();
}
return ;
}

另一种方法:DFS      16MS

 #include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
using namespace std;
int b[][]={{,},{-,},{,},{,-}};
int a[][];
int n,m,s;
void dfs(int i,int j)
{
int k,x,y;
s++;
a[i][j]=; //标记
for(k=;k<;k++)
{
x=i+b[k][];
y=j+b[k][] ;
if(x>&&x<=n&&y>&&y<=m&&a[x][y]==) //满足条件
dfs(x,y);
}
}
int main()
{
int t,a1,b1,i,j,MAX;
while(~scanf("%d%d%d",&n,&m,&t))
{
s=;
memset(a,,sizeof(a));
for(i=;i<t;i++)
{
scanf("%d %d",&a1,&b1);
a[a1][b1]=;
}
MAX=;
for(i=;i<=n;i++)
for(j=;j<=m;j++) // 遍历能够开始的点
if(a[i][j]==)
{
dfs(i,j);
if(s>MAX) //找到最大值
MAX=s;
s=;
}
printf("%d\n",MAX);
}
return ;
}

C 大意是:一个Z层x*y的楼房,要从起点到中点,问最少要走多少步?     6个方向    Dungeon Master    POJ 2251

代码:     0MS

 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int number,Z,X,Y,x1,y1,z1,x2,y2,z2;
const int add[][]={{,,},{,-,},{,,},{-,,},{,,},{,,-}}; //上下左右前后6个方向
char a[][][];
class K
{
public:
int x,y,z,step;
}k[];
void bfs(int z,int x,int y)
{
int f=,r=,i,hx,hy,hz;
k[].x=x; //开始位置
k[].y=y;
k[].z=z;
k[].step=;
a[z][x][y]='#'; //标记
while(f<r)
{
for(i=;i<;i++)
{
hx=k[f].x+add[i][];
hy=k[f].y+add[i][];
hz=k[f].z+add[i][];
if(hx>= && hx<X && hy>= && hy<Y && hz>= && hz<Z && (a[hz][hx][hy]=='.' ||a[hz][hx][hy]=='E') )
{
if(a[hz][hx][hy]=='E')
{number=k[f].step+; return;}
k[r].x=hx;
k[r].y=hy;
k[r].z=hz;
k[r++].step=k[f].step+;
a[hz][hx][hy]='#';
}
}
f++;
}
return;
}
int main()
{
while(scanf("%d%d%d",&Z,&X,&Y)&&Z&&Y&&X)
{
int i,j,k;
memset(a,,sizeof(a));
for(i=;i<Z;i++) //输入地图
for(j=;j<X;j++)
scanf("%s",a[i][j]);
for(i=;i<Z;i++)
for(j=;j<X;j++)
for(k=;k<Y;k++)
if(a[i][j][k]=='S') //起点
{
x1=j;
y1=k;
z1=i;
}
number=;
bfs(z1,x1,y1);
if(number==)
printf("Trapped!\n");
else
printf("Escaped in %d minute(s).\n",number);
}
return ;
}

D  大意是:给出一个数m,要用n个数来凑,这n个数分别是a1,a2,a3a.....an.输出加法式    Sum It Up    HDU 1258

代码:      15MS

  #include<stdio.h>
2 int t,n,flag,a[],b[];
void dfs(int j,int k,int g)
 {
int i;
if(j>t)
return ;
if(j==t) //凑成了t
{
flag=; //至少有一种凑的方法
for(i=;i<g-;i++)
printf("%d+",b[i]);
printf("%d\n",b[g-]); //打出等式
return ;
}
int last=-;
for(i=k;i<n;i++) //和每个排在自己之后的数加一次
{
if(j+a[i]>t) //超过就跳过
continue;
if(a[i]!=last) //不等于最后加的一个数,否则等式一样
22 {
last=b[g]=a[i]; //更新最后加的数
dfs(j+a[i],i+,g+);
}
}
}
int main()
{
int i;
while(~scanf("%d%d",&t,&n)&&n&&t)
{
flag=;
for(i=;i<n;i++)
scanf("%d",&a[i]);
printf("Sums of %d:\n",t);
dfs(, , );
if(flag)
printf("NONE\n");
}
}

另一份代码:    0ms

 #include <stdio.h>
#include<string.h>
const int N=;
int a[N],n,t,flag;
bool vis[N];
void print()
{
flag=;
bool bol=;
int i;
for (i=;i<=n;i++)
if (vis[i]) //判断要不要加
{
if (bol) printf("+%d",a[i]);
else {bol=; printf("%d",a[i]);} //加的第一个数
}
printf("\n");
}
void dfs(int s,int p)
{
if (s==t) {print(); return;}
int i;
for (i=p+;i<=n;i++) //s和最后一个加数之后所有的数加一次
{
vis[i]=; //标记,代表加了这个数
if (s+a[i]<=t)
dfs(s+a[i],i);
vis[i]=; //不满足则退回到上一步
while (i<=n && a[i]==a[i+]) //一样的数不用再加,否则会重复
i++;
}
}
int main()
{
int i;
while (scanf("%d%d",&t,&n),n||t)
{
flag=;
for (i=;i<=n;i++)
scanf("%d",&a[i]);
printf("Sums of %d:\n",t);
dfs(,);
if (!flag) printf("NONE\n");
}
return ;
}

E大意是:在N*N的棋盘上放N个皇后,每两个皇后不能在同一行,同一列,也不能再同一斜线上(45°斜线),问有多少种方法?

这一道题我们是水过去的,因为规定了N<=10,所以只有10种情况,一一列举出来。╮(╯▽╰)╭

以下解释&&代码来自http://blog.sina.com.cn/s/blog_696187fd0100p5ri.html#       (我修改了一些地方)

方法一:  递归回溯    //会超时......

 #include<stdio.h>
#include<math.h>
#define N 15
int n; //皇后个数
int sum = ; //可行解个数
int x[N]; //皇后放置的列数
int place(int k)
{
int i;
for(i=;i<k;i++)
if(fabs(k-i)==fabs(x[k]-x[i]) || x[k] == x[i]) //fabs(k-i)==fabs(x[k]-x[i])是在同一斜线上,x[k] == x[i]在同一列
return ;
return ;
}
int queen(int t)
{
if(t>n) //当放置的皇后超过n时,可行解个数加1
sum++;
else
for(int i=;i<=n;i++)
{
x[t] = i; //标明第t个皇后放在第i列
if(place(t)) //如果可以放在某一位置,则继续放下一皇后
queen(t+);
}
return sum;
}
int main()
{
while(~scanf("%d",&n)&&n)
{
sum=;
int t = queen();
printf("%d\n",t);
}
return ;
}

方法二:迭代回溯      可以理解但是....他是肿么想出来的.....其实和上面那个方法差不多,但是不是用递归实现的

 #include<stdio.h>
#include<math.h>
#define N 15
int n;
int sum = ;
int x[N];
int place(int k) //判断能不能放这~~~
{
int i;
for(i=;i<k;i++)
if(fabs(k-i)==fabs(x[k]-x[i]) || x[k] == x[i]) //fabs(k-i)==fabs(x[k]-x[i])是在同一斜线上,x[k] == x[i]是在同一列上
return ;
return ;
}
int queen()
{
x[] = ;
int t=;
while(t>)
{
x[t]+=;
while(x[t]<=n && !place(t)) //一列列试,不行则放下一列
x[t]++;
if(x[t]<=n )
if(t==n)
sum++;
else
x[++t] = ;
else
t--; //满了则退回一步
}
return sum;
}
int main()
{
int t;
while(~scanf("%d",&n),n)
{
sum=;
t = queen();
printf("%d\n",t);
}
return ;
}

这样用记忆法才不会超时      15MS

 #include <stdio.h>
#include <iostream>
#include <math.h>
using namespace std;
int n,x[],sum,a[];
int place(int i)
{
for(int j=;j<i;j++)
if(fabs(i-j)==fabs(x[i]-x[j]) || x[i]==x[j])
return ;
return ;
}
int qeen(int i)
{
if(i>n)
sum++;
else
for(int j=;j<=n;j++)
{
x[i]=j;
if(place(i))
qeen(i+);
}
return sum;
}
int main()
{
for(n=;n<=;n++)
{
sum=;
a[n]=qeen();
}
while(~scanf("%d",&n)&&n)
printf("%d\n",a[n]);
return ;
}

E 大意是:找出棋盘上最多能放的棋子数,不能同一行同一列(隔开了就可以),允许在同一斜线上。

如图:

1:棋盘。2:正确的方法(也是最多的),3正确,4&5错误.

和N皇后有点像,指不过斜线也可以放,而且有墙,隔开也可以放。

代码:     来自:http://blog.csdn.net/hcbbt/article/details/9420387       15MS,头文件加上#include<iostream> using namespace std;之后时间为0MS

 #include <cstdio>
const int maxn = ;
char map[maxn][maxn];
int ans, n;
bool isok(int x, int y)
{
for (int i = x + ; i <= n && map[i][y] != 'X'; i++) //遇到'X'就不再搜了
if(map[i][y] == '')
return false;
for (int i = x - ; i >= && map[i][y] != 'X'; i--)
if(map[i][y] == '')
return false;
for (int i = y + ; i <= n && map[x][i] != 'X'; i++)
if (map[x][i] == '')
return false;
for (int i = y - ; i >= && map[x][i] != 'X'; i--)
if (map[x][i] == '')
return false;
return true;
}
void dfs(int x, int y, int p)
{
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
if (map[i][j] == '.' && isok(i, j))
{
map[i][j] = ''; //代表已经放了一颗棋子
dfs(i, j, p + );
map[i][j] = '.';
}
if (ans < p)
ans = p;
}
int main()
{
while (scanf("%d", &n) && n)
{
gets(map[]); //可改成用scanf("%s",map[i]+1);来输入
for (int i = ; i <= n; i++)
gets(map[i] + );
ans = ;
dfs(, , );
printf("%d\n", ans);
}
return ;
}

G:G和C几乎一模一样,就不解释了:

代码:         31MS

 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int number,quan,N,x1,y1,z1,x2,y2,z2;
const int add[][]={{,,},{,-,},{,,},{-,,},{,,},{,,-}};
char a[][][];
class K
{
public:
int x,y,z,step;
}k[];
void bfs(int z,int x,int y)
{
int f=,r=,i,hx,hy,hz;
memset(k,,sizeof(k));
k[].x=x;
k[].y=y;
k[].z=z;
k[].step=;
a[z][x][y]='X';
while(f<r)
{
for(i=;i<;i++)
{
hx=k[f].x+add[i][];
hy=k[f].y+add[i][];
hz=k[f].z+add[i][]; if(hx>= && hx<N && hy>= && hy<N && hz>= && hz<N && a[hz][hx][hy]=='O')
{
if(hz==z2 && hx==x2 && hy==y2)
{number=k[f].step+; return;}
k[r].x=hx;
k[r].y=hy;
k[r].z=hz;
k[r++].step=k[f].step+;
a[hz][hx][hy]='X';
}
}
f++;
}
return;
} int main()
{
char w[],q[];
while(~scanf("%s",q))
{
scanf("%d",&N);
int i,j,k;
memset(a,,sizeof(a));
for(i=;i<N;i++)
{
for(j=;j<N;j++)
scanf("%s",a[i][j]);
}
scanf("%d%d%d",&z1,&x1,&y1);
scanf("%d%d%d",&z2,&x2,&y2);
scanf("%s",w);
quan=;
if(a[z2][x2][y2]=='O') quan++;
if(a[z2][x2][y2]=='X') {a[z2][x2][y2]='O';quan--;}
number=;
if(z1==z2 && x1==x2 && y1==y2) {printf("%d 0\n",quan);continue;}
bfs(z1,x1,y1);
if(number==)
printf("NO ROUTE\n");
else
printf("%d %d\n",number+quan,number);
}
return ;
}

第三次组队赛 (DFS&BFS)的更多相关文章

  1. POJ 3083 -- Children of the Candy Corn(DFS+BFS)TLE

    POJ 3083 -- Children of the Candy Corn(DFS+BFS) 题意: 给定一个迷宫,S是起点,E是终点,#是墙不可走,.可以走 1)先输出左转优先时,从S到E的步数 ...

  2. DFS/BFS+思维 HDOJ 5325 Crazy Bobo

    题目传送门 /* 题意:给一个树,节点上有权值,问最多能找出多少个点满足在树上是连通的并且按照权值排序后相邻的点 在树上的路径权值都小于这两个点 DFS/BFS+思维:按照权值的大小,从小的到大的连有 ...

  3. 【DFS/BFS】NYOJ-58-最少步数(迷宫最短路径问题)

    [题目链接:NYOJ-58] 经典的搜索问题,想必这题用广搜的会比较多,所以我首先使的也是广搜,但其实深搜同样也是可以的. 不考虑剪枝的话,两种方法实践消耗相同,但是深搜相比广搜内存低一点. 我想,因 ...

  4. ID(dfs+bfs)-hdu-4127-Flood-it!

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4127 题目意思: 给n*n的方格,每个格子有一种颜色(0~5),每次可以选择一种颜色,使得和左上角相 ...

  5. [LeetCode] 130. Surrounded Regions_Medium tag: DFS/BFS

    Given a 2D board containing 'X' and 'O' (the letter O), capture all regions surrounded by 'X'. A reg ...

  6. HDU 4771 (DFS+BFS)

    Problem Description Harry Potter has some precious. For example, his invisible robe, his wand and hi ...

  7. DFS/BFS视频讲解

    视频链接:https://www.bilibili.com/video/av12019553?share_medium=android&share_source=qq&bbid=XZ7 ...

  8. [LeetCode]695. 岛屿的最大面积(DFS/BFS)、200. 岛屿数量(DFS/BFS待做/并差集待做)

    695. 岛屿的最大面积 题目 给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合.你可以假设二维矩阵的四个边缘都被 ...

  9. POJ2308连连看dfs+bfs+优化

    DFS+BFS+MAP+剪枝 题意:       就是给你一个10*10的连连看状态,然后问你最后能不能全部消没? 思路:      首先要明确这是一个搜索题目,还有就是关键的一点就是连连看这个游戏是 ...

随机推荐

  1. VIM 移动

    基础 字符移动 k 上移 k h 左移 h l l 右移 j j 下移 你也可以使用键盘上的方向键来移动,但这么做h j k l的存在就失去了意义 之所以使用h j k l来控制方向,其主要目的是让你 ...

  2. oc34--instancetype和id的区别

    // Person.h #import <Foundation/Foundation.h> @interface Person : NSObject @property int age; ...

  3. Detach a Database

    https://msdn.microsoft.com/en-us/library/ms191491.aspx 方法一:Using SQL Server Management Studio To det ...

  4. C#如何读写和创建INI文件(经典)转

    C#如何读写和创建INI文件 分类: c#程序设计2011-11-27 20:42 4935人阅读 评论(2) 收藏 举报 inic#stringbuffernullfile 在做项目过程中,有时需要 ...

  5. 电脑升级win10后visio的问题

    上周由于电脑意外蓝屏,系统从win7升级到了win10,昨天工作写文档时才发现缺少画图的工具,于是按照了visio2013,在编辑设计图时发现,一旦用visio打开或编辑图后再到word里设计图的内容 ...

  6. 杂项-人物:Alan cooper

    ylbtech-杂项-人物:Alan cooper Alan Cooper ,“VB之父”“交互设计之父”,荣获视窗先锋奖(Microsoft Windows Pioneer)和软件梦幻奖(Softw ...

  7. Enter the path to the kernel header files for the 3.18.0-kali1-686-pae kerne vmware tool

    安装VMWare Tools出现提示:Enter the path to the kernel header files for the 3.18.0-kali1-686-pae kerne? 201 ...

  8. CMS内容管理系统 -- WorkSpace

  9. [Apple开发者帐户帮助]三、创建证书(3)创建企业分发证书

    作为Apple Developer Enterprise Program的成员,您可以创建多个企业分发证书. 所需角色:帐户持有人或管理员. 在证书,标识符和配置文件中,从左侧的弹出菜单中选择iOS, ...

  10. Cookie、Token与Session介绍(非原创)

    文章大纲 一.Cookie介绍二.Token介绍三.Session介绍四.Token.Cookie与Session比较五.参考文章   一.Cookie介绍 1. Cookie是什么 cookie机制 ...