谷歌笔试题“滑动解锁”深度搜索哪错了?

网上说是谷歌在线笔试题。

滑动解锁是智能手机一项常用的功能。你需要在3x3的点阵上,从任意一个点开始,反复移动到一个尚未经过的"相邻"的点。这些划过的点所组成的有向折线,如果与预设的折线在图案、方向上都一致,那么手机将解锁。两个点相邻当且仅当以这两个点为端点的线段上不存在尚未经过的点。此外,这条折线还需要至少经过4个点。

为了描述方便,我们给这9个点从上到下、从左到右依次编号1-9。那么1->2->3是不合法的,因为长度不足。1->3->2->4也是合不法的,因为1->3穿过了尚未经过的点2。2->4->1->3->6是合法的,因为1->3时点2已经被划过了。

作为一个爱逛知乎的好少年,小Hi已经知道一共有389112种不同的解锁方案。不过小Hi不满足于此,他希望知道,当已经瞥视到一部分折线的情况下,有多少种不同的方案。

遗憾的是,小Hi看到的部分折线既不一定是连续的,也不知道方向。例如看到1-2-3和4-5-6,那么1->2->3->4->5->6,1->2->3->6->5->4, 3->2->1->6->5->4->8->9等都是合法的方案。

输入

第一行包含一个整数T(1 <= T <= 10),代表测试数据组数。

每个测试数据第一行是一个整数N(0 <= N <= 8),代表小Hi看到的折线段数目。

以下N行每行包含两个整数X, Y (1 <= X, Y <= 9),代表小Hi看到点X和点Y是直接相连的。

输出

对于每组数据输出合法的方案数目。

我的哪里错了?思路参考网上博客的http://blog.csdn.net/u013455341/article/details/44700561
只是dfs时不好确定那些顶点可以走,需要标记一下非相连顶点,然后求出非相邻顶点的中间节点
#include <iostream>
#include <memory>
#include <stdio.h>
#include <stdlib.h>

using namespace std ;

int knows[10][10] ;//保存必须包含的边(已知的折线段)
int record[10][10] ;//相邻的边值为1,不相邻的值为0
int visited[10] ;
int N ; //已知折线段数目

void init(    ) {
	record[1][3] = record[4][6] = record[7][9] = 1;//横着的非相邻顶点
	record[3][1] = record[6][4] = record[9][7] = 1;
	record[1][7] = record[2][8] = record[3][9] = 1;//竖着的非相邻顶点
	record[7][1] = record[1][7] = record[9][3] = 1;
	record[1][9] = record[9][1] = record[3][7] = record[7][3] = 1;//斜着的非相邻顶点
}

int res;
void dfs( int depth ,  int cur  , int contains  ) {

	if ( depth >= 4 ) {
		if (contains == N)//看到的边全部包含
			res++;
		//不返回,因为要在当前基础上继续扩展
	}

	for (int i = 1; i <= 9; ++i) {
		if ( visited[ i ] == 0 ) {
			visited[ i ] = 1 ;
			
			if (knows[cur][i] == 1)//如果这条边是必须走的边
				contains++ ;
                        //如果是相邻顶点,或者非相邻顶点但是中间顶点已经走过了
			if(  record[cur][i]==0 ||  ( record[cur][i]==1 && visited[ (cur+i)/2 ]==1   )         )
				 dfs(  depth + 1, N, contains) ;

			//回溯,取消这条边
			visited[ i ] = 0 ;
			if (knows[cur][i] == 1)//如果这条边是必须走的边
				contains-- ;
		}
	}
	//cout << res << endl;
}

int main(   )
{
	int T ;//测试数据组数
	cin >> T;
	while ( T-- ) {
		cin >> N;

		memset(record, 0, sizeof(record));
		init(  ) ;
		memset(knows, 0, sizeof(knows));

		for (int i = 0; i < N; ++i) {
			int x, y; 
			cin >> x >> y;
			knows[x][y] = knows[y][x] = 1 ;
		}
	
		res = 0 ;

		for ( int i = 1; i <= 9; ++i ) {//从当前i顶点出发
			memset( visited, 0, sizeof(visited) ) ;
			
			visited[ i ] = 1; //i顶点已走因此depth=1
			dfs(1, i, 0);
			
			visited[ i ] = 0 ;
		}
		cout << res<< endl;
	}
	return 0 ;
}

全部评论
其实真实开发中滑动解锁不需要算法。
点赞 回复 分享
发布于 2017-04-09 23:33
找到哪里错了***了record[7][1] = record[1][7] = record[9][3] = 1; record[1][7] 应该改为 record[8][2] 。还有 dfs( depth + 1, N, contains) ; 调用错了啊 dfs( depth + 1, i, contains) ;
点赞 回复 分享
发布于 2017-04-10 16:54

相关推荐

不愿透露姓名的神秘牛友
11-27 10:46
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务