1. 程式人生 > >UVA - 1533 - Moving Pegs

UVA - 1533 - Moving Pegs

con close tdi truct 位與 hid show tps play

題目鏈接:UVA-1533

題目大意:

有一個棋盤如下,黑色表示有棋子,白色表示空,棋盤初始狀態為有一個位置n為空,其他位置都有棋子。

技術分享

每次可以選擇一個棋子在一條直線上隔一個或連續多個棋子跳到空白位置,然後這一個或多個棋子就被拿走,問最少幾步可以使棋盤上的棋子拿走到只剩下一個且位置和初始空白位置相同。輸出幾步和每步的起始與落子位置。輸出字典序最小的解,無解輸出IMPOSSIBLE。

題目分析:

可以直接BFS計算。

但是狀態太多,需要進行狀態壓縮。

將當前狀態用二進制保存。

每個點最多可以有六種移動方向,用數組表示出每個點的移動方向。

關鍵是二進制運算符的用法,如下:

1.& 按位與 如果兩個相應的二進制位都為1,則該位的結果值為1,否則為0

2.| 按位或 兩個相應的二進制位中只要有一個為1,該位的結果值為1
3.^ 按位異或 若參加運算的兩個二進制位值相同則為0,否則為1
4.~ 取反 ~是一元運算符,用來對一個二進制數按位取反,即將0變1,將1變0
5.<< 左移 用來將一個數的各二進制位全部左移N位,右補0
6.>> 右移 將一個數的各二進制位右移N位,移到右端的低位被舍棄,對於無符號數,高位補0

給出代碼:

技術分享
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <vector>
  5
#include <string> 6 #include <queue> 7 #include <algorithm> 8 using namespace std; 9 const int N=15; 10 int mp[1 << N]; 11 int flag[15][6] = {{-1,-1,-1,-1,2,3},{-1,1,-1,3,4,5},{1,-1,2,-1,5,6}, 12 {-1,2,-1,5,7,8},{2,3,4,6,8,9},{3,-1,5,-1,9,10}, 13 {-1
,4,-1,8,11,12},{4,5,7,9,12,13},{5,6,8,10,13,14}, 14 {6,-1,9,-1,14,15},{-1,7,-1,12,-1,-1},{7,8,11,13,-1,-1}, 15 {8,9,12,14,-1,-1},{9,10,13,15,-1,-1},{10,-1,14,-1,-1,-1} 16 }; 17 int n; 18 struct P 19 { 20 int S; 21 int num; 22 int mark[16][3]; 23 int step; 24 }; 25 int bfs(int s) 26 { 27 queue<P> p; 28 while(!p.empty()) 29 p.pop(); 30 P a; 31 a.S=s; 32 a.step=0; 33 a.num=1; 34 p.push(a); 35 while(!p.empty()) 36 { 37 //cout<<"*"<<endl; 38 P u=p.front(); 39 p.pop(); 40 // cout<<u.S<<endl; 41 for(int i=0; i<15; i++) 42 { 43 if(u.S&(1<<i)) 44 { 45 for(int j=0; j<6; j++) 46 { 47 P b=u; 48 int cur=i; 49 if(flag[i][j]!=-1&&b.S&(1<<(flag[i][j]-1))) 50 { 51 while(cur!=-1&&b.S&(1<<cur)) 52 { 53 b.S^=(1<<cur); 54 cur=flag[cur][j]-1; 55 b.num++; 56 } 57 if(cur<0) 58 continue; 59 b.S|=(1<<cur); 60 b.step=u.step+1; 61 b.mark[b.step][0]=i; 62 b.mark[b.step][1]=cur; 63 b.num--; 64 if(!mp[b.S]) 65 { 66 if(b.num==14&&b.S&(1<<(n-1))) 67 { 68 printf("%d\n%d %d", b.step, b.mark[1][0] + 1, b.mark[1][1] + 1); 69 for (int k = 2; k <= b.step; k++) 70 printf(" %d %d", b.mark[k][0] + 1, b.mark[k][1] + 1); 71 printf("\n"); 72 return 1; 73 } 74 mp[b.S]=1; 75 p.push(b); 76 } 77 78 } 79 } 80 } 81 } 82 } 83 return 0; 84 } 85 int main() 86 { 87 int T; 88 cin>>T; 89 while(T--) 90 { 91 cin>>n; 92 memset(mp,0,sizeof(mp)); 93 int temp = ((1 << 15) - 1) ^ (1 << (n - 1)); 94 mp[temp]=1; 95 int res = bfs(temp); 96 if (!res) 97 printf("IMPOSSIBLE\n"); 98 } 99 return 0; 100 }
View Code

UVA - 1533 - Moving Pegs