标签:io ar os sp for 问题 bs 代码 amp
题目:有一个类似跳棋的游戏,一共有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; }
标签:io ar os sp for 问题 bs 代码 amp
原文地址:http://blog.csdn.net/mobius_strip/article/details/41665351