题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3861
想不大ZOJ访问速度这么慢。
题意:给定九宫格中的一些数字,求这些数字能组成的密码方案种数。主要判断能否继续往下搜索
代码:
#include<iostream>
#include<sstream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<string>
#define LL long long
#define INF 0x7fffffff
using namespace std;
int a[20],n,vis[20],vis2[20];
int cnt,tot,ans[20];//分别记录方案数,和有效点数及答案数组
int isok(int x,int y){//判断从x到y是否合法,即中间点是否访问过
if(x+y==10 && !vis2[5]) return 0;
if(min(x,y)==1 && max(x,y)==3 && !vis2[2]) return 0;
if(min(x,y)==7 && max(x,y)==9 && !vis2[8]) return 0;
if(min(x,y)==1 && max(x,y)==7 && !vis2[4]) return 0;
if(min(x,y)==3 && max(x,y)==9 && !vis2[6]) return 0;
return 1;
}
void dfs(int t,int count,int op){//目前所在下标,已经ans存储的个数,输出标志
if(count==tot){
if(op){
for(int i=1;i<tot;i++)
printf("%d ",ans[i]);
printf("%d\n",ans[tot]);
return;
}
cnt++;return;
}
for(int i=0;i<tot;i++)
if(!vis[i] && isok(a[t],a[i])){
vis[i]=1;vis2[a[i]]=1;
ans[count+1]=a[i];
dfs(i,count+1,op);
vis[i]=0;vis2[a[i]]=0;
}
}
int main(){
//freopen("D:\\in.txt","r",stdin);
int T;cin>>T;
while(T--){
cin>>n;
tot=0;
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++){
int t;cin>>t;
if(!vis[t]) vis[t]=1,a[tot++]=t;//感觉可能存在重复输入
}
sort(a,a+tot);
cnt=0;
memset(vis,0,sizeof(vis));//ans数组访问标志
memset(vis2,0,sizeof(vis2));//九宫格访问标志
for(int j=0;j<2;j++){//这里进行了两次DFS,一次求cnt,一次输出,是为了节约空间
if(j) cout<<cnt<<endl;
for(int i=0;i<tot;i++){
vis[i]=1;vis2[a[i]]=1;
ans[1]=a[i];
dfs(i,1,j);
vis[i]=0;vis2[a[i]]=0;
}
}
}
return 0;
}