题目:有一些格子,这些格子都是挨着的,并排摆放的,有的格子里面有石子,有的没有,当满足一下条件的时候,就会做一下的操作:
条件:用1表示有格子,0表示没有。如果连续的三个格子的状态是011,就把它给成100, 相当于将最后边的1放到最左边,然后去掉中间的那个1;如果是110,就改成001,即将最左的1放大最右,然后去掉中间的那个。
分析:
还是搜索。
这道题,一共只有12个格子,从数据上来讲,dfs是没有问题的。
其次,位运算压缩状态,记录已经遍历过的状态。
最后就是用位运算判断有无石子,若满足条件,就修改值。
取反就和1做异或运算,判断就和1做与运算。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = ( (1<<12) + 10 );
bool vis[N];
int n, now, ans, snum, dl, tmp;
char data[15];
void dfs( int state, int x ) {
vis[state] = true;
if ( x > ans ) ans = x;
for ( int i = 0; i < dl-2; ++i ) {
int s1 = ( 1 << ( dl-i-1 ) ), s2 = ( 1 << ( dl-i-2 ) ), s3 = ( 1 << ( dl-i-3 ) );
//cout << s1 << " " << s2 << " " << s3 << endl;
if ( (state & s1) == 0 ) {
if ( (state & s2) > 0 && (state & s3) > 0 ) {
//cout << state << endl;
tmp = state ^ s3 ^ s2 ^ s1;
//cout << tmp << endl;
if ( !vis[tmp] ) dfs( tmp, x+1 );
}
}
else {
if ( (state & s2) > 0 && (state & s3) == 0 ) {
tmp = state ^ s1 ^ s2 ^ s3;
//cout << tmp << endl;
if ( !vis[tmp] ) dfs( tmp, x+1 );
}
}
}
}
int main()
{
scanf("%d", &n);
getchar();
while( n-- ) {
scanf("%s", data);
now = ans = snum = 0;
memset(vis, 0, sizeof(vis));
dl = strlen(data);
for ( int i = 0; i < dl; ++i ) {
now <<= 1;
if ( data[i] == 'o' ) now++, snum++;
}
//cout << now << endl;
dfs( now, 0 );
printf("%d\n", snum-ans);
}
}