P3084 黑白棋游戏

  P3084 黑白棋游戏
 时间: 1000ms / 空间: 65536KiB / Java类名: Main

描述

  黑白棋游戏的棋盘由4×4方格阵列构成。棋盘的每一方格中放有1枚棋子,共有8枚白棋子和8枚黑棋子。这16枚棋子的每一种放置方案都构成一个游戏状态。在棋盘上拥有1条公共边的2个方格称为相邻方格。一个方格最多可有4个相邻方格。在玩黑白棋游戏时,每一步可将任何2个相邻方格中棋子互换位置。对于给定的初始游戏状态和目标游戏状态,编程计算从初始游戏状态变化到目标游戏状态的最短着棋序列。

输入格式

  输入文件共有8行。前四行是初始游戏状态,后四行是目标游戏状态。每行4个数分别表示该行放置的棋子颜色。“0”表示白棋;“1”表示黑棋。

输出格式

  输出文件,一行,是着棋步数n。

测试样例1

输入

1111
0000
1110
0010
1010
0101 
1010 
0101

输出

4

用二进制,BFS搜索所有的状态,假如当前状态是

1111
0000
1110
0010
=1111000011100010 = 61666
那么下一步状态可以有两种转移方式:
1.左右的不同数字交换
2.上下的不同数字交换
对于第一种情况,我们首先要检查二进制下相邻两位是不是相同的, 我们构造一个数字y ,y与x对应的待检查的两位数字都是1,其他都是0,比如1111000011100010 我们构造 y = 0000000000000011 。如果是相同的1,那么x & y == y,如果是相同的0,那么我们令tem =  1111111111111111 - y 得到的tem除待检查的两位是0外,其他的都是1,那么有 (x | tem) == tem。
如果不相同,那么就找下一步的状态。x & y得到的是那两位的值,x - (x & y)得到的是除去那两位剩下的值,那么x + (x & y) ^ y就是下一步的状态。
y的初始值是3,之后移位即可,但要注意不同行的也可能相邻,比如第一行的最后和第二行的第一个。那么排除掉y = 24,384,6144三种情况即可。
对于第二种情况, 我们构造的y初始是10001,因为这样是上下相邻的,而且不用排除一些y,其他的域第一种情况相同

这个题我在tyvj上面AC了,洛谷和Codevs上面也有这个题,只不过还要输出互换的过程。但是wa了……(其实我的代码是对的,但是他们没有special judge……)


在tyvj上面AC的代码:
#include 
      
      
       
       
#include 
       
       
#include 
        
        
         
         
#include 
         
         
          
          
#include 
          
          
            #include 
           
             #include 
            
              #include 
             
               #include 
              
                #include 
               
                 #include 
                
                  #include 
                 
                   #include 
                  
                    #include 
                   
                     #include 
                    
                      #include 
                     
                       #include 
                      
                        #include 
                       
                         #define pi acos(-1.0) #define maxn (101000 + 50) #define mol 1000000009 #define inf 0x3f3f3f3f #define Lowbit(x) (x & (-x)) using namespace std; typedef long long int LLI; int dp[maxn],sta = 0,aim = 0; int Read(int n) { int cnt = 0; for(int i = 0;; i ++) { char c; scanf("%c",&c); if(c == '0' || c == '1') { n = n * 2 + c - '0'; cnt ++; } if(cnt == 16) return n; } } int BFS(int s,int e) { memset(dp,-1,sizeof(dp)); dp[s] = 0; queue 
                        
                          Que; Que.push(s); while(!Que.empty()) { int x = Que.front(); // printf("------%d--------\n",x); Que.pop(); for(int i = 3; i < (1 << 16); i = (i << 1)) { if(i == 24 || i == 384 || i == 6144) continue; int tem = (1 << 16) - i - 1; // printf("%d **%d ** %d ** %d\n",i,x & i,tem,x | tem); if(((x & i) == i) || ((x | tem) == tem)) continue; else { // printf("---\n"); int part1 = x & i; int y = x - part1; part1 = part1 ^ i; y = y + part1; if(dp[y] == -1) { Que.push(y); dp[y] = dp[x] + 1; } } } for(int i = 17; i < (1 << 16); i = (i << 1)) { int tem = (1 << 16) - 1 - i; // printf("%d %d\n",i,tem); if(((x & i) == i) || ((x | tem) == tem)) continue; else { int part1 = x & i; int y = x - part1; part1 = part1 ^ i; y = y + part1; if(dp[y] == -1) { Que.push(y); dp[y] = dp[x] + 1; } } } } return dp[aim]; } int main() { // freopen("in.txt","r",stdin); sta = Read(sta); aim = Read(aim); BFS(sta,aim); printf("%d\n",dp[aim]); return 0; } //1111 //0000 //1110 //0010 //1111000011100001 61665 //1111000011100100 61668 //1111000011010010 61650 //1111000010100110 61606 //1111000001101010 61546 //1111001011000010 62146 //1111010010100010 62626 //1111100001100010 63586 //1110000111100010 57826 //1101001011100010 53986 //1011010011100010 46306 //0111100011100010 30946 
                         
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
          
         
         
        
        
      
      

0000
1110
0010
还有输出交换过程的代码:
#include 
    
    
     
     
#include 
     
     
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
          #include 
         
           #include 
          
            #include 
           
             #include 
            
              #include 
             
               #include 
              
                #include 
               
                 #include 
                
                  #include 
                 
                   #include 
                  
                    #include 
                   
                     #include 
                    
                      #include 
                     
                       #define pi acos(-1.0) #define maxn (101000 + 50) #define mol 1000000009 #define inf 0x3f3f3f3f #define Lowbit(x) (x & (-x)) using namespace std; typedef long long int LLI; int dp[maxn],sta = 0,aim = 0; int last[maxn]; int Read(int n) { int cnt = 0; for(int i = 0;; i ++) { char c; scanf("%c",&c); if(c == '0' || c == '1') { n = n * 2 + c - '0'; cnt ++; } if(cnt == 16) return n; } } int BFS(int s,int e) { memset(dp,-1,sizeof(dp)); dp[s] = 0; queue 
                      
                        Que; Que.push(s); while(!Que.empty()) { int x = Que.front(); Que.pop(); for(int i = 3; i < (1 << 16); i = (i << 1)) { if(i == 24 || i == 384 || i == 6144) continue; int tem = (1 << 16) - i - 1; if(((x & i) == i) || ((x | tem) == tem)) continue; else { int part1 = x & i; int y = x - part1; part1 = part1 ^ i; y = y + part1; if(dp[y] == -1) { Que.push(y); dp[y] = dp[x] + 1; last[y] = x; } } } for(int i = 17; i < (1 << 16); i = (i << 1)) { int tem = (1 << 16) - 1 - i; if(((x & i) == i) || ((x | tem) == tem)) continue; else { int part1 = x & i; int y = x - part1; part1 = part1 ^ i; y = y + part1; if(dp[y] == -1) { Que.push(y); dp[y] = dp[x] + 1; last[y] = x; } } } } return dp[aim]; } int main() { // freopen("in.txt","r",stdin); sta = Read(sta); aim = Read(aim); printf("%d\n",BFS(sta,aim)); int p = aim; while(p != sta) { int x = p,flag = 0; int y = last[p]; pair 
                       
                         a,b; for(int i = 15; i >= 0; i --) { if(x % 2 != y % 2) { if(flag == 0) { a.first = i / 4 + 1; a.second = i % 4 + 1; flag = 1; } else { b.first = i / 4 + 1; b.second = i % 4 + 1; } } x /= 2; y /= 2; } if(a.first > b.first) swap(a,b); else if(a.first == b.first && a.second > b.second) swap(a,b); printf("%d%d%d%d\n",a.first,a.second,b.first,b.second); p = last[p]; } return 0; } //1111 //0000 //1110 //0010 //1111000011100001 61665 //1111000011100100 61668 //1111000011010010 61650 //1111000010100110 61606 //1111000001101010 61546 //1111001011000010 62146 //1111010010100010 62626 //1111100001100010 63586 //1110000111100010 57826 //1101001011100010 53986 //1011010011100010 46306 //0111100011100010 30946 
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
        
       
       
      
      
    
    

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值