您的位置:首页 > 其它

【叶节点记忆式/深搜式DFS_路径搜索问题】滑动解锁

2014-10-09 22:26 363 查看
作为一个爱逛知乎的好少年,小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是直接相连的。


输出

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

显然,一个solution就是搜索树上的一个路径。

该路径不停加深,直到延伸到叶节点,然后记录路径(solution),并返回(注意叶节点已经做了该做的处理即记录了答案,返回空就行)。

典型的深搜式DFS:

#include <iostream>
#include <vector>
#include <string.h>
using namespace std;
#define abs(a) (a<0?0-(a):a)
int tt[9][9];

// cached tt[a][b]
int get(int a,int b){
if(tt[a][b]!=-1) return tt[a][b];
int s=abs(a-b);
//// if a->b is a horse-path
// if(abs(a%3-b%3)==2&&abs(a/3-b/3)==1||
// abs(a/3-b/3)==1&&abs(a%3-b%3)==2)
// return -2;//a->b is impossible
int t=0;
if(a%3==b%3) {
if(s<6) t=-2;
else t=(a+b)/2;
}
else if(a/3==b/3){
if(s<2) t=-2;
else t=(a+b)/2;
}
else{
int x=min(a,b),y=max(a,b);//@error: x=max(a,b),y=min(a,b)
if(x==2&&y==6||x==0&&y==8) t=(x+y)/2;
else t=-2;
}
return tt[a][b]=t;
}
void init(){
memset(tt,-1,sizeof(tt));
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
get(i,j);
}
void dfs(int &cnt,int curCnt,vector<int> &path,bool map[][9],bool visit[],int depth,int idx){
if(curCnt==0){
//four points at least
if(depth>=4) cnt++;//a solution
}
if(depth==9){
//// debug
// if(curCnt==0){
// for(int i=0;i<9;i++){
// cout<<path[i]+1<<" ";
// }cout<<endl;
// }
return;
}

for(int j=0;j<9;j++){
if(visit[j]) continue;

int tmp=-1;
int preCnt=curCnt;
if(idx>=0){
tmp=get(idx,j);
if(tmp>=0){
if(!visit[tmp]) continue;//tmp not passed yet
}
if(map[idx][j]) curCnt--;
}
visit[j]=true;
path.push_back(j);

dfs(cnt,curCnt,path,map,visit,depth+1,j);

path.pop_back();
curCnt=preCnt;
visit[j]=false;
}
}
int main(){
int casen;cin>>casen;
bool map[9][9];bool visit[9];
init();
for(int casei=0;casei<casen;casei++){
memset(map,0,sizeof(map));
memset(visit,0,sizeof(visit));
int edgen;cin>>edgen;
for(int i=0;i<edgen;i++){
int a,b;cin>>a>>b;a--,b--;
map[a][b]=map[b][a]=true;
}
int cnt=0;
vector<int> path;
dfs(cnt,edgen,path,map,visit,0,-1);
cout<<cnt<<endl;
}
}


考虑另外改变一个条件,如果允许看到的路径<123>可以等价于从1直接到3。则解法会变的更多。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: