题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=150302
题意:给定一个九宫格,给定一些能走的数字,走法按照手机图案的解锁方法来解锁,起点不定,求合法路线的总数并按照字典序输出他们
思路:暴力破解+DFS。刚开始的想法是把路线看成二维,一条一条判断是否合法,这种方法最大的问题就是会超时,而且例如1->3>1>4的路线不好表示,要假定一个点只能经过两次,搜索的深度瞬间增加了n个指数级。实际上由于点数小,可以把路线看成一维,只是有些路线在某些情况下不合法,穷举即可。莫名其妙的做了很久。
错误源码:
#include <iostream>
#include <cstdio>
#include <string>
#include <string.h>
#include <map>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <functional>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cassert>
#include <bitset>
#include <stack>
#include <ctime>
#include <list>
#define INF 0x7fffffff
#define max3(a,b,c) (max(a,b)>c?max(a,b):c)
#define min3(a,b,c) (min(a,b)<c?min(a,b):c)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int const MAXN = 10;
int use[MAXN],uu[MAXN];
int org[MAXN];
int vis[4][4];
int re[MAXN];
int rec[362880+1];
int n;
int dy[12] = {-2,-1,0,1,2,-1,1,-2,-1,0,1,2};
int dx[12] = {-1,-1,-1,-1,-1,0,0,1,1,1,1,1};
int dir[MAXN] = {1,1,1e1,1e2,1e3,1e4,1e5,1e6,1e7,1e8};
int num,total;///num for all rec,total for not repeaty ones.
bool valid(int a)
{
if(a<1 || a>3)
return false;
return true;
}
bool cmp(int a,int b)
{
return a<b;
}
bool equ(int a[],int b[])
{
int i;
for(i=0; i<n; i++)
if(a[i]!=b[i])
return false;
return true;
}
int X(int i)
{
return i%3?i/3+1:i/3;
}
int Y(int i)
{
return i%3?i%3:3;
}
void init()
{
num = total = 0;
memset(rec,0,sizeof(rec));
memset(use,0,sizeof(use));
int i,temp;
for(i=0; i<n; i++){
scanf("%d", &temp);
use[temp] = 1;
org[i] = temp;
}
sort(org,org+n);
}
void dfs(int now,int mark)
{
int i;
if(mark==n){
// if(num>0 && equ(rec[num],re))
// return;
num++;
for(i=0; i<n; i++){
rec[num]= rec[num]*10 + re[i];
}
// printf("\nnum = %d\n",num);
// for(i=0; i<n; i++)
// printf("%d ",re[i]);
// printf("\n\n");
}
// printf("now = %d mark = %d\n",now,mark);
for(i=0; i<12; i++){
// printf("now = %d\n",now);
int tx = X(now)+dx[i];
int ty = Y(now)+dy[i];
int t = (tx-1)*3 + ty;
// printf("first tx = %d ty = %d t = %d\n",tx,ty,t);
if(valid(tx)&&valid(ty) && use[t] && vis[tx][ty]<2){
// printf("second tx = %d ty = %d t = %d\n",tx,ty,t);
// for(i=0; i<mark; i++)
// printf("%d ",re[i]);
// printf("\n");
vis[tx][ty]++;
if(uu[t]==0){
uu[t] = 1;
re[mark] = t;
dfs(t,mark+1);
uu[t] = 0;
}
else
dfs(t,mark);
vis[tx][ty]--;
}
}
}
void solve()
{
int i,j;
memset(vis,0,sizeof(vis));
memset(uu,0,sizeof(uu));
for(i=0; i<n ;i++){
int t = org[i];
int tx = X(t);
int ty = Y(t);
vis[tx][ty] = 1;
re[0] = t;
uu[t] = 1;
// printf("org = %d\n",org[i]);
dfs(t,1);
vis[tx][ty] = 0;
uu[t] = 0;
}
sort(rec,rec+num,cmp);
for(i=1; i<=num; i++)
if(rec[i]!=rec[i-1])
total++;
printf("%d\n",total);
for(i=1; i<=num; i++){
if(i==0 ||(i>0 && rec[i-1]!=rec[i])){
int f = 1;
int tt = rec[i];
for(j=0; j<n; j++){
if(f) f=0;
else printf(" ");
printf("%d",tt/dir[n-j]);
tt = tt%dir[n-j];
// printf("\nrec = %d\n",rec[i]);
}
// printf("%d",rec[i]);
printf("\n");
}
}
}
int main()
{
int t;
scanf("%d", &t);
while(t--){
scanf("%d", &n);
init();
solve();
}
return 0;
}
AC源码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int const MAXN = 500000;
int dir[2] = {-1,1};
int rec[MAXN][10],org[10],vis[10],re[10];
int n,num;
bool equ(int a[],int b[])
{
int i;
for(i=0; i<n; i++)
if(a[i]!=b[i])
return false;
return true;
}
bool valid(int a[])
{
int tvis[10];
memset(tvis,0,sizeof(tvis));
for(int i=0; i<n; i++){
if(a[i]>9 || a[i]<1)
return false;
for(int j=0; j<2; j++){
if(a[i]==1 && ((a[i+dir[j]]==3&&tvis[2]==0) || (a[i+dir[j]]==9&&tvis[5]==0) || (a[i+dir[j]]==7&&tvis[4]==0)))
return false;
if(a[i]==2 && ((a[i+dir[j]]==8&&tvis[5]==0)))
return false;
if(a[i]==3 && ((a[i+dir[j]]==7&&tvis[5]==0) || (a[i+dir[j]]==9&&tvis[6]==0)))
return false;
if(a[i]==4 && ((a[i+dir[j]]==6&&tvis[5]==0)))
return false;
if(a[i]==7 && ((a[i+dir[j]]==9&&tvis[8]==0)))
return false;
}
tvis[a[i]] = 1;
}
// puts("sdas\n");
return true;
}
void init()
{
memset(vis,0,sizeof(vis));
num = 0;
int i;
scanf("%d",&n);
for(i=0; i<n; i++)
scanf("%d",&org[i]);
sort(org,org+n);
}
void dfs(int cnt)
{
int i;
if(cnt == n+1){
if(valid(re) && (num==0 || (num>0 && !equ(re,rec[num-1])))){
for(i=0; i<n; i++)
rec[num][i] = re[i];
// printf("num = %d\n",num);
num++;
}
return;
}
for(i=0; i<n; i++){
int t = org[i];
if(vis[t]==0){
vis[t] = 1;
re[cnt-1] = t;
dfs(cnt+1);
vis[t] = 0;
}
}
}
void solve()
{
dfs(1);
printf("%d\n",num);
int i,j;
// printf("%d\n",num);
for(i=0; i<num; i++){
int f = 1;
// puts("dasda\n");
for(j=0; j<n; j++){
if(f) f=0;
else printf(" ");
printf("%d",rec[i][j]);
}
printf("\n");
}
}
int main()
{
int t; scanf("%d",&t);
while(t--){
init();
solve();
}
return 0;
}