HUD ACM 1401 Solitaire (双向广搜+8进制状态压缩)
http://acm.hdu.edu.cn/showproblem.php?pid=1401
题意:给出4个点,问在一个8*8的方格中,能不能在8步以内由初始状态变换为目标状态
输入有两行,分别表示初始状态和目标.
每行有八个数字,两个数字为一组表示一个点的坐标
思路:由于点只在一个8*8的方格中移动,所以每一个坐标分别有8种状态,最大状态为88 = 16777216
1 #include <iostream> 2 #include <queue> 3 using namespace std; 4 struct Node{ 5 int x; 6 int y; 7 }; 8 struct Map{ 9 Node node[4]; 10 int step; 11 }; 12 Map s; 13 Map e; 14 int Point[4][2] = {0,-1,0,1,-1,0,1,0};//上 下 左 右 15 int num[] = {1,8,64,512,4096,32768,262144,2097152};//表示每一位八进制数 16 char visit[20000000];//记录状态 用int会超内存 17 bool cmp(Node a,Node b){ 18 if(a.x == b.x){ 19 return a.y > b.y; 20 } 21 return a.x > b.x; 22 } 23 int Hash(Map p){//哈希算法,哈希后可以用一个整数表示一个图的状态 24 sort(p.node,p.node+4,cmp);//每次哈希前进行排序,判重 25 int sum = 0; 26 int i; 27 for(i=0;i<4;i++){ 28 sum += p.node[i].x * num[i*2]; 29 sum += p.node[i].y * num[i*2+1]; 30 } 31 return sum; 32 } 33 //有相同 == 1 没有相同 == 0 越界 == -1 34 int Used(int x,int y,Map mid){ 35 if(x >0 && x <= 8 && y > 0 && y <= 8){ 36 int i; 37 for(i=0;i<4;i++){ 38 if(mid.node[i].x == x && mid.node[i].y == y){ 39 return 1; 40 } 41 } 42 return 0; 43 } 44 return -1; 45 } 46 int DoubleBFS(){//双向广搜即从初始状态和目标状态同时搜索,当搜索发现有重叠时表示能找到 47 queue <Map> q[2]; 48 s.step = 0; 49 q[0].push(s); 50 int HashS = Hash(s); 51 int HashE = Hash(e); 52 if(HashS == HashE){ 53 return 1; 54 } 55 visit[HashS] = 0; 56 while(!q[0].empty()){ 57 Map mid= q[0].front(); 58 q[0].pop(); 59 if(mid.step >= 4){ 60 break; 61 } 62 int i,j; 63 mid.step++; 64 for(i=0;i<4;i++){ 65 for(j=0;j<4;j++){ 66 int x,y; 67 x = mid.node[j].x + Point[i][0]; 68 y = mid.node[j].y + Point[i][1]; 69 if(Used(x,y,mid) == 1){ 70 x +=Point[i][0]; 71 y +=Point[i][1]; 72 } 73 if(Used(x,y,mid) == 0){ 74 Map flag = mid; 75 flag.node[j].x = x; 76 flag.node[j].y = y; 77 int result = Hash(flag); 78 if(visit[result] == -1){ 79 visit[result] = 0; 80 q[0].push(flag); 81 } 82 } 83 } 84 } 85 } 86 87 if(visit[Hash(e)] == 0){ 88 return 1; 89 } 90 91 e.step = 0; 92 q[1].push(e); 93 while(!q[1].empty()){ 94 Map mid= q[1].front(); 95 q[1].pop(); 96 if(mid.step >= 4){ 97 break; 98 } 99 int i,j; 100 mid.step++; 101 for(i=0;i<4;i++){ 102 for(j=0;j<4;j++){ 103 int x,y; 104 x = mid.node[j].x + Point[i][0]; 105 y = mid.node[j].y + Point[i][1]; 106 if(Used(x,y,mid) == 1){ 107 x +=Point[i][0]; 108 y +=Point[i][1]; 109 } 110 if(Used(x,y,mid) == 0){ 111 Map flag = mid; 112 flag.node[j].x = x; 113 flag.node[j].y = y; 114 int result = Hash(flag); 115 if(visit[result] == 0){ 116 return 1; 117 } 118 else{ 119 if(visit[result] == -1){ 120 visit[result] = 1; 121 q[1].push(flag); 122 } 123 } 124 } 125 } 126 } 127 } 128 return 0; 129 } 130 int main(){ 131 while(cin>>s.node[0].x>>s.node[0].y){ 132 int i; 133 memset(visit,-1,sizeof(visit)); 134 for(i=1;i<4;i++){ 135 cin>>s.node[i].x>>s.node[i].y; 136 } 137 for(i=0;i<4;i++){ 138 cin>>e.node[i].x>>e.node[i].y; 139 } 140 if(DoubleBFS()){ 141 cout<<"YES"<<endl; 142 } 143 else{ 144 cout<<"NO"<<endl; 145 } 146 } 147 }