题意:水平移动一行或者一列字母。使中间的8个字母相同要多少步?
思路:把每一种字母分别考虑,到到每一种状态步数的最小值就是答案;
好开心,刷到榜首了。。第一次榜首有名啊!!!
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
int que[1<<24];
short visit[1<<24];
int tmp[5],c;
int inline col1(int k,int s)
{
c = -1;
for(int i=0; i<4; i++)
{
c -= (1<<(i*6+k));
tmp[i]=s&(1<<(i*6+k));
}
s=s&c;
tmp[0]<<=18;
tmp[1]>>=6;
tmp[2]>>=6;
tmp[3]>>=6;
s=s+tmp[0]+tmp[1]+tmp[2]+tmp[3];
return s;
}
int inline col2(int k,int s)
{
c = -1;
for(int i=0; i<4; i++)
{
c -= (1<<(i*6+k));
tmp[i]=s&(1<<(i*6+k));
}
s=s&c;
tmp[0]<<=6;
tmp[1]<<=6;
tmp[2]<<=6;
tmp[3]>>=18;
s=s+tmp[0]+tmp[1]+tmp[2]+tmp[3];
return s;
}
int inline row1(int k,int s)
{
c = 63<<(k*6);
int tmp = c&s;
s -= tmp;
int t = tmp&(1<<(k*6));
tmp -= t;
tmp>>=1;
tmp +=(t<<5);
return s+tmp;
}
int inline row2(int k,int s)
{
c = 63<<(k*6);
int tmp = c&s;
s -= tmp;
int t = tmp&(1<<(k*6+5));
tmp -= t;
tmp<<=1;
tmp +=(t>>5);
return s+tmp;
}
void init()
{
int rear=0,fron=0;
que[rear++]=124800;
visit[124800] = 1;
while(rear>fron)
{
int e = que[fron++],t;
for(int i=0; i<6; i++)
{
t = col1(i,e);
if(!visit[t])
{
visit[t] = visit[e]+1;
que[rear++] = t;
}
t = col2(i,e);
if(!visit[t])
{
visit[t] = visit[e]+1;
que[rear++] = t;
}
}
for(int i=0; i<4; i++)
{
t = row1(i,e);
if(!visit[t])
{
visit[t] = visit[e]+1;
que[rear++] = t;
}
t = row2(i,e);
if(!visit[t])
{
visit[t] = visit[e]+1;
que[rear++] = t;
}
}
}
}
int main()
{
freopen("in.txt","r",stdin);
int cas,T = 1;
scanf("%d",&cas);
init();
while(cas--)
{
int b=0,g=0,w=0;
char a[20];
for(int i=0; i<4; i++)
{
scanf("%s",a);
for(int j=0; j<6; j++)
if(a[j]=='W')
w+=(1<<(i*6+j));
else if(a[j]=='G')
g+=(1<<(i*6+j));
else
b+=(1<<(i*6+j));
}
printf("Case %d: %d\n",T++,min(visit[b],min(visit[g],visit[w]))-1);
}
return 0;
}