您的位置:首页 > 大数据 > 人工智能

uva 10651 Pebble Solitaire

2015-08-27 12:19 561 查看
此题不会做,看别人做法瞬间明白了(晕)

转载的连接

原题:

Pebble solitaire is an interesting game. This is a game where you are given a board with an arrangement

of small cavities, initially all but one occupied by a pebble each. The aim of the game is to remove

as many pebbles as possible from the board. Pebbles disappear from the board as a result of a move.

A move is possible if there is a straight line of three adjacent cavities, let us call them A, B, and C,

with B in the middle, where A is vacant, but B and C each contain a pebble. The move constitutes of

moving the pebble from C to A, and removing the pebble in B from the board. You may continue to

make moves until no more moves are possible.

In this problem, we look at a simple variant of this game, namely a board with twelve cavities

located along a line. In the beginning of each game, some of the cavities are occupied by pebbles. Your

mission is to find a sequence of moves such that as few pebbles as possible are left on the board.




Input

The input begins with a positive integer n on a line of its own. Thereafter n different games follow.

Each game consists of one line of input with exactly twelve characters, describing the twelve cavities of

the board in order. Each character is either ‘-’ or ‘o’ (The fifteenth character of English alphabet in

lowercase). A ‘-’ (minus) character denotes an empty cavity, whereas a ‘o’ character denotes a cavity

with a pebble in it. As you will find in the sample that there may be inputs where no moves is possible.

Output

For each of the n games in the input, output the minimum number of pebbles left on the board possible

to obtain as a result of moves, on a row of its own.

Sample Input

5

—oo——-

-o–o-oo—-

-o—-ooo—

oooooooooooo

oooooooooo-o

Sample Output

1

2

3

12

1

大意:

给你12个洞,有的洞里有可能有石子。如果一个石子隔着一个石子且相隔的地方是空的,则可以跳过。相邻的那个石子可以拿掉。问最后剩多少。

[code]#include <cstdio>
#include <cstdlib>
#include <cstring>

#define min(a,b) (((a) < (b)) ? (a) : (b))

int dp[4100];

int solve(int n)
{
    if (dp
 != -1)
        return dp
;

    dp
 = 0;
    for (int i = 0; i < 12; ++i)
        if (n & (1 << i))
            dp
 += 1;

    for (int i = 0; i < 10; ++i)
    {
        int t;
        if ((n&(1<<i)) && (n&(1<<(i+1))) && !(n&(1<<(i+2))))
        {
            t = n;
            t &= ~(1 << i);
            t &= ~(1 << (i+1));
            t |= 1 << (i+2);
            dp
 = min(dp
, solve(t));
        }

        if (!(n&(1<<i)) && (n&(1<<(i+1))) && (n&(1<<(i+2))))
        {
            t = n;
            t &= ~(1 << (i+1));
            t &= ~(1 << (i+2));
            t |= 1 << i;
            dp
 = min(dp
, solve(t));
        }
    }
    return dp
;
}

int main()
{
    memset(dp, -1, sizeof(dp));

    int cases;
    scanf("%d", &cases);
    while (cases--)
    {
        char str[20];
        int n = 0;

        scanf("%s", str);
        for (int i = 0; i < 12; ++i)
            if (str[i] == 'o')
                n ^= 1 << i;

        printf("%d\n", solve(n));
    }
    return 0;
}


思路

刚看到这题寻思用搜索暴力求解,但是…. 如果用暴力就对不起作者的意图了,想到用dp。因为起始状态不唯一,考虑到可以从任意一个点进行dp,想到用记忆化搜索。但是如何保存状态,没想明白。后来看了别人的代码知道了要用到状态压缩(其实早就应该想到,毕竟只有12个点,数量有限),转移方程也非常见到。无非就是两个状态,要么向左移动,要么向右移动。记录下即可~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: