首页 > 代码库 > UVa 10651 - Pebble Solitaire

UVa 10651 - Pebble Solitaire

题目:有一个类似跳棋的游戏,一共有12个位置‘o‘代表棋子‘-‘代表空位,

            ‘oo-‘可以转化成‘--o‘,‘-oo‘可以转化成‘o--‘,给你初始状态,问最后,至少剩下几个棋子。

分析:dp,记忆化搜索,位运算。利用搜索在相邻状态间dp即可。

            每个状态的最优解为他能转化所有状态中的最优解。

            因为,一共有2^12 = 4096个状态,每次找到解即存储,不会重复计算,所以时间方面没问题。

            利用一个12位整数表示一个状态,‘o‘用1表示,‘-‘用0表示,则’---oo-------‘为24(2进制000000011000)

           (这里是从左向右代表低位到高位,倒过来也可以)

            通过观察可以发现‘oo-‘(011)转化成‘--o‘(100),‘-oo‘(110)转化成‘o--‘(001)都是对应为取反;

            直接利用7(2进制111)进行异或即可,而对应额可以跳的状态为3(2进制011)与6(2进制110);

说明:详细参考代码。

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cstdio> 
#include <cmath>

using namespace std;

char buf[13];
int  F[4100];

int dfs(int s)
{
	if (F[s] < 13) return F[s];
	int Min = 12;
	for (int i = 0 ; i < 10 ; ++ i)
		if (((s>>i)&7) == 3 || ((s>>i)&7) == 6)
			Min = min(Min, dfs(s^(7<<i)));
	if (Min == 12) {
		for (int i = 0 ; i < 12 ; ++ i)
			Min -= !(s&(1<<i));
	}
	return F[s] = Min;
}

int main()
{
	for (int i = 0 ; i < 4100 ; ++ i)
		F[i] = 13;
	int n,v;
	while (~scanf("%d",&n))
	for (int i = 1 ; i <= n ; ++ i) {
		scanf("%s",buf);
		v = 0;
		for (int j = 0 ; j < 12 ; ++ j) {
			v <<= 1;
			if (buf[j] == 'o') v += 1;
		} 
		printf("%d\n",dfs(v));
	}
    return 0;
}


UVa 10651 - Pebble Solitaire