uva_10651_Pebble Solitaire(状态压缩DP)

题目意思很明确,12这个数字很有状态压缩的意味
这一题的阶段就是按照left -> right 的顺序DP
这里一共有2^12个状态,从1 到 2^12 的数字,每个数字的二进制表示这一行的状态
状态:dp[i]表示该状态的游戏最终结果
状态转移:dp[i] = min(dp[j]), j就是从i的状态经过游戏规则所能转换的状态
ans = dp[n]

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define MAXBIT  12
#define INF     0x3f3f3f3f
#define MAXN    1<<(MAXBIT+1)

int dp[MAXN];

int dfs(const int &idx)
{
        if( -1 != dp[idx] ) {
                return dp[idx];
        }
        int val(idx), rst(INF), flag(0), cnt(0), tmp;
        for(int i = 0; i < MAXBIT; i ++) {
                cnt += ((1<<i)&val)? 1 : 0;
                if( (1<<i)&val && i+1 < MAXBIT && (1<<(i+1))&val ) {
                        if( i > 0 && !((1<<(i-1))&val) ) {              //move to left
                                tmp = val; tmp ^= (1<<(i-1));
                                tmp ^= (1<<(i+1)); tmp ^= (1<<i); flag = 1;
                                rst = min(rst, dp[tmp] = (-1 == dp[tmp])? dfs(tmp) : dp[tmp]);
                        }
                        if( i+2 < MAXBIT && !((1<<(i+2))&val) ) {       //move to right
                                tmp = val; tmp ^= (1<<(i+2));
                                tmp ^= (1<<(i+1)); tmp ^= (1<<i); flag = 1;
                                rst = min(rst, dp[tmp] = (-1 == dp[tmp])? dfs(tmp) : dp[tmp]);
                        }
                }
        }
        if( !flag ) {
                return dp[idx] = cnt;
        }
        return dp[idx] = rst;
}

int conversion(const char *str)
{
        int rst(0);
        for(int i = strlen(str)-1; i >= 0; i --) {
                if( 'o' == str[i] ) {
                        rst += (1<<(strlen(str)-i-1));
                }
        }
        return rst;
}

int main(int argc, char const *argv[])
{
#ifndef ONLINE_JUDGE
        freopen("test.in", "r", stdin);
#endif
        int n;
        char str[MAXBIT+1];
        memset(dp, -1, sizeof(dp));
        for(int i = 1<<MAXBIT; i >= 0; i --) {
                dp[i] = (-1 == dp[i])? dfs(i) : dp[i];
        }
        while( ~scanf("%d", &n) ) {
                for(int i = 0; i < n; i ++) {
                        scanf("%s", str);
                        printf("%d\n", dp[ conversion(str) ]);
                }
        }
        return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值