uva10651 - Pebble Solitaire(记忆化搜索)

题目:uva10651 - Pebble Solitaire(记忆化搜索)


题目大意:12个坑,每个坑里面可以放卵石,也可以不放。然后如果出现00- 或是 -00这样的情况,就可以变成--0和0--。给定初始的状态问最总剩余的卵石个数。

解题思路:这里只有12的位置,并且每个位置只有两种可能,所以可以用二进制数来表示所有的状态。判断卵石的情况每次都是3个3个判断,发现能够转换,就变换成另一个状态直到不能转换为止。因为每个状态最后剩下的卵石是确定的。所以可以用记忆化搜索,之前查找过的状态要将值记录下来,这样下次查找的时候就不用在做一次。这样之前的dp数组就要有一个初始值代表还没有访问过,并且因为这里是要取最小值,所以这里的初始值可以放13.

           二进制操作 :

                               n & (1<<i) 代表取出第i位的值, n | (1<<i) 把第i位变成1, n & (~(1 <<i)) 把第i位变成0。

代码:

#include <cstdio>
#include <cstring>

const int N = 12;
const int maxn = 1 << N;

int dp[maxn];

void init () {

	for (int i = 0; i < maxn; i++)
		dp[i] = N + 1;
}

int Min (const int a, const int b) { return a < b ? a: b; }

int d (int n) {

	if (dp[n] != N + 1)
		return dp[n];

	int t;
	for (int i = 0; i < N - 2; i++) {
		 
		t = n;
		if ((n & (1 << i)) && (n & (1 << (i + 1))) && ! (n & (1 << (i + 2)))) {

		  t &= ~(1 << i);
		  t &= ~(1 << (i + 1));
		  t |= 1 << (i + 2);
		  dp[n] = Min (dp[n] , dp[t] = Min (dp[t], d(t)));
		} else if (!(n & (1 << i)) && (n & (1 << (i + 1))) && (n & (1 << (i  + 2)))) {

		  t |= 1 << i;
		  t &= ~(1 << (i + 1));
		  t &= ~(1 << (i + 2));
		  dp[n] = Min (dp[n], dp[t] = Min (dp[t], d(t)));
				}
	}
	
	int cnt = 0;
	for (int i = 0; i < N; i++)
		if (n & (1 << i))
			cnt++;
	return dp[n] = Min(dp[n], cnt);
}

int main () {

	int t;
	int n;
	char ch;
	scanf ("%d%*c", &t);
	init ();
	while (t--) {

		n = 0;
		for (int i = 0; i < N; i++) {

			scanf ("%c", &ch); 
			if (ch == 'o')
				n = n | (1 << i);	
		}
		getchar();
		printf ("%d\n", d(n));
	}
	return 0;
}



你可能感兴趣的:(uva10651 - Pebble Solitaire(记忆化搜索))