ZOJ1008 一个简单的dfs回溯问题,为啥老是出现超时错误,我和同样可以通过的代码思路基本一样

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ZOJ1008 一个简单的dfs回溯问题,为啥老是出现超时错误,我和同样可以通过的代码思路基本一样相关的知识,希望对你有一定的参考价值。

网上博客找到的可以通过测试的标准答案:
#include<iostream>
#include<string.h>
using namespace std;

struct Node
int left, right, top, buttom;
bool operator == (const Node &a) const
return left == a.left && right == a.right && top == a.top && buttom == a.buttom;

;

Node E[35];
int Sum[35], Map[11][11], Num;

void GetE(int n)
memset(Sum, 0, sizeof(Sum));
for (int i = 0; i < n*n; ++i)
cin >> E[i].top >> E[i].right >> E[i].buttom >> E[i].left;
for (int j = 0; j <= i; ++j)
if (E[j] == E[i])
Sum[j]++;
break;





bool DFS(int pos, int n)
if (pos == n * n) return true;
int x = pos / n, y = pos % n;
//cout << x << " " << y << endl;
for (int i = 0; i < n*n; ++i)
if (Sum[i])
if (x > 0 && E[i].top != E[Map[x - 1][y]].buttom) continue;
if (y > 0 && E[i].left != E[Map[x][y - 1]].right) continue;
Map[x][y] = i;
--Sum[i];
if (DFS(pos + 1, n) == true) return true;
else
++Sum[i];



return false;


int main()
int Case = 0;
while (cin >> Num && Num)
if (Case > 0) cout << endl;
GetE(Num);
//cout << "1" <<endl;
if (DFS(0, Num)) cout << "Game " << ++Case << ": Possible" << endl;
else cout << "Game " << ++Case << ": Impossible" << endl;

return 0;

下面是我自己写的,其实思路和上面这个完全一样,只是我把SUM[i]改成了vis[],另外图的形式表示解空间我用一个数组表示的,而且我用样例测试后出现的答案是正确的,但一旦提交就出现超时错误,很不理解。
#include<iostream>
#include<string.h>
using namespace std;
int initial[35][4];
int vis[35];
int solution[35];
bool backtrace(int m, int n)
int x, y;
x = m / n;
y = m % n;
if (m == (n*n))
return true;

else
for (int p = 0; p < (n*n); p++)
if (vis[p] == 0)
if (x > 0 && initial[p][0] != initial[solution[m - n]][2])continue;
if (y > 0 && initial[p][3] != initial[solution[m - 1]][1])continue;
solution[m] = p;
vis[p] = 1;
if (backtrace(m + 1, n))
return true;
else
vis[p] = 0;



return false;

int main()

int n,num=0;
while (cin >> n&&n)
if (num > 0)
cout << endl;
num++;
memset(vis, 0, sizeof(vis));
for (int i = 0; i < (n*n); i++)
for (int k = 0; k < 4; k++)
cin >> initial[i][k];

if (backtrace(0, n))
cout << "Game " << num << ": Possible" << endl;
else
cout << "Game " << num << ": Impossible" << endl;

return 0;

首先选定图的类别(有向图、无向图),再选定图的存储结构,根据输入的顶点或者边建立图;并把相应的邻接表或者邻接矩阵输出;
根据已有的邻接矩阵或邻接表用递归方法编写深度优先搜索遍历算法,并输出遍历结果;
图的深度遍历原则:

1 如果有可能,访问一个领接的未访问的节点,标记它,并把它放入栈中。

2 当不能执行规则 1 时,如果栈不为空,则从栈中弹出一个元素。

3 如果不能执行规则 1 和规则 2 时,则完成了遍历。

代码中的图使用的是Graph 图-邻接矩阵法 来表示,其他的表示法请见:Graph 图-邻接表法

代码中的Stack为辅助结构,用来记载访问过的节点。栈的详细描述可以见:ArrayStack 栈 ,LinkedStack 栈 。

Vertex表示图中的节点,其中包含访问,是否访问,清除访问标志的方法。 Graph.main:提供简单测试。代码可以以指定下标的节点开始作深度遍历。 代码比较简单,除了Graph.dsf(int i)深度优先遍历算法外没有过多注释。
参考技术A 首先选定图的类别(有向图、无向图),再选定图的存储结构,根据输入的顶点或者边建立图;并把相应的邻接表或者邻接矩阵输出; 参考技术B Vertex表示图中的节点,其中包含访问,是否访问,清除访问标志的方法。 Graph.main:提供简单测试。代码可以以指定下标的节点开始作深度遍历。 代码比较简单,除了Graph.dsf(int i)深度优先遍历算法外没有过多注释。Vertex表示图中的节点,其中包含访问,是否访问,清除访问标志的方法。 Graph.main:提供简单测试。代码可以以指定下标的节点开始作深度遍历。 代码比较简单,除了Graph.dsf(int i)深度优先遍历算法外没有过多注释。Vertex表示图中的节点,其中包含访问,是否访问,清除访问标志的方法。 Graph.main:提供简单测试。代码可以以指定下标的节点开始作深度遍历。 代码比较简单,除了Graph.dsf(int i)深度优先遍历算法外没有过多注释。 参考技术C edghjkkbvccjkllmnbvcxftuiooytrilkjhgrdsdgvvcvbbnnkllbvcccnmmkjgthiijhdghkjh:khgxchjkbcchyrfkoitdfjnvvcxfjjbgyjklpjggffedfhkkknnmnbvcbkiuhgfdsretuuhhhhuijgteeyugvhikbvffryj

Num 36 : ZOJ 2100 [ 深度优先搜索算法 ] [ 回溯 ]



        该题是用回溯法来解决的题:


题目:

Seeding

Time Limit: 2 Seconds      Memory Limit: 65536 KB

It is spring time and farmers have to plant seeds in the field. Tom has a nice field,which is a rectangle with n * m squares. There are big stones in some of the squares.

Tom has a seeding-machine. At the beginning, the machine lies in the top left corner of the field. After the machine finishes one square, Tom drives it into an adjacent square, and continues seeding. In order to protect the machine, Tom will not drive it into a square that contains stones. It is not allowed to drive the machine into a square that been seeded before, either.

Tom wants to seed all the squares that do not contain stones. Is it possible?


Input

The first line of each test case contains two integers n and m that denote the size of the field. (1 < n, m < 7) The next n lines give the field, each of which contains m characters. ‘S‘ is a square with stones, and ‘.‘ is a square without stones.

Input is terminated with two 0‘s. This case is not to be processed.


Output

For each test case, print "YES" if Tom can make it, or "NO" otherwise.


Sample Input

4 4
.S..
.S..
....
....
4 4
....
...S
....
...S
0 0


Sample Output

YES
NO


         题目大意:

             从左上角開始行进,能不能不走回头路的把地图上全部点走一遍;( S代表障碍物 )。


         题目分析:

             从左上角開始,利用回溯法进行深搜。推断有没有一种情况。能不回头的把一条路走完;


AC代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int x,y,m,n,snum,max=0,flag;
char map[10][10];
void fun(int x,int y)
{
	if(x<1||x>m||y<1||y>n) return;
    if(map[x][y]==‘S‘) return;
    if(flag==1) return;
	map[x][y]=‘S‘;
	snum++;
	if(snum==m*n)
    {
    	flag=1;
    	return;
    }
	fun(x-1,y);
	fun(x+1,y);
	fun(x,y-1);
	fun(x,y+1);
	snum--;
	map[x][y]=‘.‘;
}
int main()
{
	int i,j;
	while(scanf("%d%d",&m,&n),m|n)
	{
		snum=0;
		for(i=1;	i<=m;	i++)
			for(j=1;	j<=n;	j++)
			{
				scanf(" %c",&map[i][j]);
				if(map[i][j]==‘S‘) snum++;
			}
		flag=0;
		fun(1,1);
		if(flag) printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}



以上是关于ZOJ1008 一个简单的dfs回溯问题,为啥老是出现超时错误,我和同样可以通过的代码思路基本一样的主要内容,如果未能解决你的问题,请参考以下文章

ZOJ1008 Gnome Tetravex

HDU - 1560DNA sequence (dfs+回溯)

Num 36 : ZOJ 2100 [ 深度优先搜索算法 ] [ 回溯 ]

[zoj4045][思维+dfs]

ZOJ Problem Set - 1004 Anagrams by Stack (回溯法)

ACM/ICPC 之 拓扑排序+DFS(POJ1128(ZOJ1083))