数码问题,就不介绍了,百度百度,嘿嘿。
做了一天的数码,郁闷,- -
1、判断数码问题是否有解
原文地址:http://blog.csdn.net/hnust_xiehonghao/article/details/7951173
个人总结:
数码问题判断有解总结:把0看做可移动空格,这里所说的逆序数都是除开0的
一维N:
状态s和状态e的逆序数奇偶性相同,则可相互到达;反之不行
二维N*N:
空格距离:空格位置所在的行到目标空格所在的行步数(不计左右距离)
当N为奇数:状态s和状态e的逆序数奇偶性相同,则可相互到达;反之不行
当N为偶数:状态s和状态e的逆序数奇偶性相同 && 空格距离为偶数 或者 逆序数奇偶性不同 && 空格距离为奇数,则可相互到达;反之不行
三维N*N*N:
空格距离:空格位置到目标状态空格位置的yz方向的距离之和
判断同二维
SWUST OJ 306
问题描述
将1,2、、14,15这15个数字填入一个4*4的方格中,当然你会发现有个空格方格,我们用数字0来代替那个空格,如下就是一个合理的填入法: 1 2 3 4 5 6 7 8 9 10 0 12 13 14 11 15 现在的问题是:你是否能通过交换相邻的两个数字(相邻指的是上、下、左、右四个方向,而且待交换的两个数字中有一个为数字0),最后变成如下这种排列格式: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0
输入
输入包括两部分: 第一部分:输入一个数C,代表下面共有C组输入 第二部分:输入包括一个4*4的矩阵,矩阵中的数由0,1,2、、15组成。
输出
如果能通过如题方式达到目标排列,输出“YES”,否则输出“NO”。
样例
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int main() { int a[20],T,i,j; int tot,pos,dis; scanf("%d",&T); while(T--) { tot=0; for(i=0;i<16;i++) { scanf("%d",&a[i]); if(a[i]) { for(j=0;j<i;j++) { if(a[j]>a[i]) tot++; } } else pos=i; } dis=4-(pos/4+1); if(tot%2==dis%2) cout<<"YES\n"; else cout<<"NO\n"; } return 0; }
2、POJ 1077
Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 25376 | Accepted: 11106 | Special Judge |
Description
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 x
1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8
9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12
13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x
r-> d-> r->
Input
1 2 3
x 4 6
7 5 8
1 2 3 x 4 6 7 5 8
Output
Sample Input
2 3 4 1 5 x 7 6 8
Sample Output
ullddrurdllurdruldr
由于这道题是一组数据,所以需要快速解决问题,使用A*算法
好像暴力也可过,不过耗时久,我交了一个,刚好1000MS,好神奇
16MS
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <queue> #include <cmath> using namespace std; #define N 400000 int get_h(const char s[]) //估价函数,返回当前状态所有数字与其位置之差的绝对值之和 { int sum=0; for(int i=0;i<9;i++) { sum+=abs(s[i]-‘0‘-i-1); } return sum; } struct Eight { int x; int g; char s[9]; bool operator < (const Eight &t)const { return g+get_h(s)>t.g+get_h(t.s); } }; int xpos; char s[10]; int way[N]; int pre[N]; bool vis[N]; char Dir[5]="udlr"; int dir[4][2]={-1,0,1,0,0,-1,0,1}; int fac[]={1,1,2,6,24,120,720,5040,40320,326880}; int Find(char s[]) { int i,j,k,res=0; bool has[10]={0}; for(i=0;i<9;i++) { for(k=0,j=1;j<s[i]-‘0‘;j++) if(!has[j]) k++; res+=k*fac[8-i]; has[s[i]-‘0‘]=1; } return res+1; } void show() { char ans[N]; int len=0,pos=1; while(pre[pos]) { ans[len++]=way[pos]; pos=pre[pos]; } for(int i=len-1;i>=0;i--) { printf("%c",ans[i]); } printf("\n"); } void bfs() { Eight now,next; priority_queue<Eight> q; memset(vis,0,sizeof(vis)); memset(pre,0,sizeof(pre)); memset(way,0,sizeof(way)); now.g=0; now.x=xpos; strcpy(now.s,s); q.push(now); vis[Find(now.s)]=1; while(!q.empty()) { now=q.top(); q.pop(); if(vis[1]) { show(); return; } int pos1=Find(now.s); int x=now.x/3; int y=now.x%3; for(int i=0;i<4;i++) { next=now; int tx=x+dir[i][0]; int ty=y+dir[i][1]; if(tx>=0 && tx<=2 && ty>=0 && ty<=2) { next.g+=1; next.x=tx*3+ty; swap(next.s[now.x],next.s[next.x]); int pos2=Find(next.s); if(!vis[pos2]) { vis[pos2]=1; way[pos2]=Dir[i]; pre[pos2]=pos1; q.push(next); } } } } cout<<"unsolvable\n"; } int main() { while(scanf(" %c",&s[0])!=EOF) { for(int i=0;i<9;i++) { if(i) scanf(" %c",&s[i]); if(s[i]==‘x‘) { s[i]=‘9‘; xpos=i; } } bfs(); } return 0; }
3、HDU 1043
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 12761 Accepted Submission(s): 3475
Special Judge
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 x
1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8
9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12
13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x
r-> d-> r->
题目描述都是一样的,不过这个是多组数据,所以需要预处理
思路同"魔板":http://www.cnblogs.com/hate13/p/4198053.html
109MS
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <queue> using namespace std; #define N 400000 struct Eight { int x; //x记录X的位置 char s[9]; }; int pre[N]; bool vis[N]; char way[N]; char Dir[5]="durl"; int dir[4][2]={-1,0,1,0,0,-1,0,1}; int fac[]={1,1,2,6,24,120,720,5040,40320,326880}; int Find(char s[]) { int i,j,k,res=0; bool has[10]={0}; for(i=0;i<9;i++) { for(k=0,j=1;j<s[i]-‘0‘;j++) if(!has[j]) k++; res+=k*fac[8-i]; has[s[i]-‘0‘]=1; } return res; } void bfs() { Eight now,next; queue<Eight> q; now.x=8; strcpy(now.s,"123456789"); q.push(now); vis[Find(now.s)]=1; while(!q.empty()) { now=q.front(); q.pop(); int pos1=Find(now.s); int x=now.x/3; int y=now.x%3; for(int i=0;i<4;i++) { next=now; int tx=x+dir[i][0]; int ty=y+dir[i][1]; if(tx>=0 && tx<=2 && ty>=0 && ty<=2) { next.x=tx*3+ty; swap(next.s[now.x],next.s[next.x]); int pos2=Find(next.s); if(!vis[pos2]) { vis[pos2]=1; pre[pos2]=pos1; way[pos2]=Dir[i]; q.push(next); } } } } } int main() { bfs(); char s[10]; while(scanf(" %c",&s[0])!=EOF) { for(int i=0;i<9;i++) { if(i) scanf(" %c",&s[i]); if(s[i]==‘x‘) s[i]=‘9‘; } int pos=Find(s); if(vis[pos]) { while(pos) { printf("%c",way[pos]); pos=pre[pos]; } printf("\n"); } else printf("unsolvable\n"); } return 0; }
4、HDU 3567
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 130000/65536 K (Java/Others)
Total Submission(s): 1243 Accepted Submission(s): 270
这个题和上一个一样,显然需要预处理,不过这个需要预处理9张表,由于起始位置都在变,所以建立映射
注意不要使用string,会MLE
还有注意字典序
1248MS
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <queue> #include <map> using namespace std; #define N 400000 struct Eight { int x; //x记录X的位置 char s[9]; }; bool vis[N]; int pre[10][N]; char way[10][N]; char Dir[]="dlru"; int dir[4][2]={1,0,0,-1,0,1,-1,0}; int fac[]={1,1,2,6,24,120,720,5040,40320,326880}; int Find(char s[]) { int i,j,k,res=0; bool has[10]={0}; for(i=0;i<9;i++) { for(k=0,j=1;j<s[i]-‘0‘;j++) if(!has[j]) k++; res+=k*fac[8-i]; has[s[i]-‘0‘]=1; } return res; } void bfs(int k) { Eight now,next; queue<Eight> q; memset(vis,0,sizeof(vis)); now.x=k-1; strcpy(now.s,"123456789"); q.push(now); vis[Find(now.s)]=1; while(!q.empty()) { now=q.front(); q.pop(); int pos1=Find(now.s); int x=now.x/3; int y=now.x%3; for(int i=0;i<4;i++) { next=now; int tx=x+dir[i][0]; int ty=y+dir[i][1]; if(tx>=0 && tx<=2 && ty>=0 && ty<=2) { next.x=tx*3+ty; swap(next.s[now.x],next.s[next.x]); int pos2=Find(next.s); if(!vis[pos2]) { vis[pos2]=1; pre[k][pos2]=pos1; way[k][pos2]=Dir[i]; q.push(next); } } } } } int main() { bfs(1); bfs(2); bfs(3); bfs(4); bfs(5); bfs(6); bfs(7); bfs(8); bfs(9); int k,i,T,iCase=1; char s1[10],s2[10]; scanf("%d",&T); while(T--) { scanf("%s%s",s1,s2); map<char,char> mp; for(i=0;i<9;i++) { if(s1[i]==‘X‘) k=i+1; mp[s1[i]]=i+‘1‘; } for(i=0;i<9;i++) { s2[i]=mp[s2[i]]; } char ans[N],len=0; int pos=Find(s2); while(pos) { ans[len++]=way[k][pos]; pos=pre[k][pos]; } printf("Case %d: %d\n",iCase++,len); for(i=len-1;i>=0;i--) cout<<ans[i]; printf("\n"); } return 0; }
原文:http://www.cnblogs.com/hate13/p/4198037.html