题意:n组测试数据,每个测试数据有12个字符构成。'o'表示当前位置有珠子,‘-’表示是空位,如果有两个珠子连在一起,且两个珠子的左右有空位,那么,就可以把一个珠子越过另一个珠子,占据空了的位置(左边或右边的空位都可以。很像跳棋)
状态压缩DP,用一个int的当前位有1表示当前位有珠子。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=10000;
int dp(int),map[N],vis[N];
int main()
{
int n;
char str[100];
scanf("%d",&n);
getchar();
while(n--)
{
memset(map,0,sizeof(map));
memset(vis,0,sizeof(vis));
gets(str);
int len=strlen(str),num=0;
for(int i=0;i<len;i++)
{
if(str[i]=='o') num^=1<<(i);
}
printf("%d\n",dp(num));
}
return 0;
}
int dp(int x)
{
if(vis[x]) return map[x];
else
{
int imin=15;
bool flag=true;
for(int i=0;i<12;i++)
{
if(x&(1<<(i))&&x&(1<<(i+1)))
{
if(i>0&&!(x&(1<<(i-1)))) {imin=min(imin,dp(x^(1<<(i-1)^(1<<i)^(1<<(i+1)))));flag=false;}
if(i+2<12&&!(x&(1<<(i+2)))) {imin=min(imin,dp(x^(1<<i)^(1<<(i+1)^(1<<(i+2)))));flag=false;}
}
}
if(flag)
{
int temp=0;
for(int i=0;i<12;i++)
{
if(x&(1<<i)) temp++;
}
vis[x]=1;
map[x]=temp;
return temp;
}
vis[x]=1;
map[x]=imin;
return imin;
}
}