pku2965 The Pilots Brothers' refrigerator

 

第一道双向广搜,188MS

题意:给定一个4X4的“+”“-”图,定义操作[i,j]为改变第i行和第j列的状态,输出使原图变为全“-”图的最小的操作数和各具体操作

#include <iostream>
using namespace std;

#define MAXN 2<<17

int r[5]={0,61440,3840,240,15};
int c[5]={0,34952,17476,8738,4369};
int rc[5][5]={
    {
0,0,0,0,0},
    {
0,32768,16384,8192,4096},
    {
0,2048,1024,512,256},
    {
0,128,64,32,16},
    {
0,8,4,2,1}
};

int open[MAXN],head,tail,mk[MAXN],st,ed,opera[MAXN],pre[MAXN],ans[MAXN],cnt;

char ss[6][6];

int change(int i,int j,int s){
    
int ns;
    
    ns
=~(r[i]^(~s));
    ns
=~(c[j]^(~ns));
    ns
=~(rc[i][j]^(~ns));

    
return ns;
}

void output(int s,int ns){
    
if(mk[s]==2){
        
int t=s;
        s
=ns;
        ns
=t;
    }
    
while(s!=st){
        ans[cnt
++]=opera[s];
        s
=pre[s];
    };

    
while(ns!=ed){
        ans[cnt
++]=opera[ns];
        ns
=pre[ns];
    };
}



void solve(){
    
int i,j,s,ns;
    
if(st==ed){
        printf(
"0\n");
        
return;
    }
    open[
0]=st;
    open[
1]=ed;
    mk[st]
=1;
    mk[ed]
=2;
    head
=0;
    tail
=2;
    
while(head<tail){

        s
=open[head++];
        
for(i=1;i<=4;i++){
            
for(j=1;j<=4;j++){
                ns
=change(i,j,s);
                
if(!mk[ns]){
                    mk[ns]
=mk[s];
                    opera[ns]
=i*10+j;
                    pre[ns]
=s;
                    open[tail
++]=ns;
                }
                
else{
                    
if(mk[s]!=mk[ns]){
                        
//cout<<"!!\n";
                        
//printf("%d %d\n",i,j);
                        ans[cnt++]=i*10+j;
                        output(s,ns);
                        
return;
                    }
                }
            }
        }
    }
    
return;
}



int main(){
    cnt
=0;
    
int i,j,k;
    
for(i=0;i<4;i++)
        gets(ss[i]);

    st
=ed=0;
    k
=0;

    
//建立st的位图
    for(i=3;i>=0;i--){
        
for(j=3;j>=0;j--){
            
if(ss[i][j]=='+')
                st
+=1<<k;
            k
++;
        }
    }

    solve();
    printf(
"%d\n",cnt);
    
for(i=0;i<cnt;i++)
        printf(
"%d %d\n",ans[i]/10,ans[i]%10);

    
return 0;
}
    
posted @ 2008-12-06 19:26  Beetlebum  阅读(400)  评论(0编辑  收藏  举报