UVa:10651 Pebble Solitaire

虽然是动规但我却是用搜索过的。

数据量比较小,每个位置就两个移动方向,因此是2^12,相当小。

用二进制表示状态(第一次独立写着玩意,居然1Y了,好不容易),1表示'o',0表示'-'。

val&x[i]用来判断该位是0或者1,val^x[i]用改变第i位的值

用dfs写的,另外开一个数组判重,如果当前状态之前出现过那就没有必要再搜下去了。最后查找出现的所有状态,选里面1个数最少的那个就是答案。

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int v[20];
char str[20];
bool vis[5000];
void dfs(int val)
{
    if(vis[val]) return ;
    else
    {
        vis[val]=true;
        int tmp=val;
        for(int i=1; i<=12; ++i)
        {
            if(i<=10&&(val&v[i])&&(val&v[i+1])&&!(val&v[i+2]))
            {
                val^=v[i];
                val^=v[i+1];
                val^=v[i+2];
                dfs(val);
            }
            val=tmp;
            if(i>=3&&(val&v[i])&&(val&v[i-1])&&!(val&v[i-2]))
            {
                val^=v[i];
                val^=v[i-1];
                val^=v[i-2];
                dfs(val);
            }
            val=tmp;
        }
    }
}
int get_1(int val)
{
    int sum=0;
    for(int i=1; i<=12; ++i)
        if(val&v[i])
            sum++;
    return sum;
}
int main()
{
    for(int i=0; i<=12; ++i)
        v[i+1]=pow(2,i);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(vis,0,sizeof(vis));
        scanf("%s",str+1);
        int s=0;
        for(int i=1; i<=12; ++i)
            if(str[i]=='o')
                s+=v[i];
        dfs(s);
        int ans=99999;
        for(int i=0; i<=4100; ++i)
            if(vis[i])
                ans=min(ans,get_1(i));
        printf("%d\n",ans);
    }
    return 0;
}


 

你可能感兴趣的:(搜索)