Pebble Solitaire - UVa 10651


http://isaac.lsu.edu/uva/106//10651.html
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 AB, 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.

5
---oo-------
-o--o-oo----
-o----ooo---
oooooooooooo
oooooooooo-o
1
2
3
12
1



int GetMin(int board)
{
    int &best = saved[board];
    
    if (best == -1)
    {
        best = GetNumPebbles(board);
        // Shift to the left
        for (int i = 2; i < NumPebbles; ++i)
        {
            if (HasPebble(i, board) && HasPebble(i - 1, board) && !HasPebble(i - 2, board))
            {
                int newBoard = board ^ (1 << i) ^ (1 << (i - 1)) ^ (1 << (i - 2));
                best = min(best, GetMin(newBoard));
            }
        }
        
        // Shift to the right
        for (int i = NumPebbles - 3; i >= 0; --i)
        {
            if (HasPebble(i, board) && HasPebble(i + 1, board) && !HasPebble(i + 2, board))
            {
                int newBoard = board ^ (1 << i) ^ (1 << (i + 1)) ^ (1 << (i + 2));
                best = min(best, GetMin(newBoard));
            }
        }
    }
    
    return best;
}
        int encoded = 0;
        for (int i = 0; i < NumPebbles; ++i)
            if (board[i] == 'o')
                encoded |= (1 << i);
        
        cout << GetMin(encoded) << '\n';


This problem is a particularization of the pebble game. In this problem you have a set of marbles and play according to some established rules. Suppose there two marbles: one at position i and the other at position i+1. You can eliminate the marble at position i+1 by hopping the marble at position i over it. Hopping  marble means moving the one that is in position i to position i+2 (i+1 is the position of the other marble). In this problem you are given a description of this game consisting of 12 spaces and some of them are filled with marbles. You should determine the minimum number of marbles that will be left after a series of movements of the marbles. A marble can hop either left or right, if there is another adjacent at marble i-1 or i+1, respectively.
Analysis:
Suppose there is a marble at position i and another marble at position i+1. Also suppose that positions i-1 and i+2 are valid positions. In this case, there are two possible movements, every movement will left one marble in the board. You can either move the marble located at i to position i+2, thus, eliminating the marble at position i+1, or you can move the marble at position i+1 to i-1, thus, eliminating the marble at position i.
Solution:
The solutions consist on using backtracking to solve the movement of the marbles. You should check for every marble, first if it can be moved. If a marble can be moved to both directions (left and right) try both possibilities, generating a new scenario for every move. That means, after performing one move (left or right), recurse so that you will get an answer based on that decision. Repeat this process for all the marbles that can be moved, and minimize the value at every ending state. i.e An ending state means that there aren’t anymore moves to perform.
http://programming-study-notes.blogspot.com/2014/05/uva-10651-pebble-solitaire.html
    跳棋,例如"oo-"表示第一和第二個位置有棋子,第三個位置是空的,因此第一個位置的棋子可以跳過第二個位置的棋子並取走第二個位置的棋子,變成"--o"。題目給定一個12個位置的棋盤,問經過不斷跳棋後,剩下最少棋子的數量。

想法:
    想到兩種方式:bitmask+bfs或是backtracking,兩種方法其實差不多,都是把所有的情況枚舉,找出最小値。第一種方法為0.009s,第二種為0.012s,時間相差不大,寫backtracking是較簡單的。

X.
http://www.voidcn.com/article/p-bvcvddwb-ge.html
状态压缩DP,用一个int的当前位有1表示当前位有珠子。
https://ageneidy.wordpress.com/2014/08/04/uva-10651-pebble-solitaire/
    static int[] masks = new int[1 << 12];
    static int setbit(int mask, int idx, int val) {
        return (val == 1) ? (mask | (1 << idx)) : (mask & ~(1 << idx));
    }
 
    static boolean getBit(int mask, int idx) {
        return ((mask >> idx) & 1) == 1;
    }
 
    static int cntBit(int mask) {
        int cnt = 0;
        while (mask > 0) {
            if (mask % 2 == 1)
                cnt++;
            mask /= 2;
        }
        return cnt;
    }
 
    private static int best(int mask) {
        // TODO Auto-generated method stub
        if (masks[mask] != -1)
            return masks[mask];
        masks[mask] = 0;
        for (int i = 0; i < 10; i++) {
            if (getBit(mask, i) && getBit(mask, i + 1) && !getBit(mask, i + 2)) {
                int tmask = mask;
                tmask = setbit(tmask, i, 0);
                tmask = setbit(tmask, i + 1, 0);
                tmask = setbit(tmask, i + 2, 1);
                masks[mask] = Math.max(masks[mask], 1 + best(tmask));
            }
            if (!getBit(mask, i) && getBit(mask, i + 1) && getBit(mask, i + 2)) {
                int tmask = mask;
                tmask = setbit(tmask, i, 1);
                tmask = setbit(tmask, i + 1, 0);
                tmask = setbit(tmask, i + 2, 0);
                masks[mask] = Math.max(masks[mask], 1 + best(tmask));
            }
        }
        return masks[mask];
    }

X. BFS
http://andrew-algorithm.blogspot.com/2014/11/uva-problem-10651-pebble-solitaire.html
https://www.cnblogs.com/yuzhaoxin/archive/2012/04/06/2435272.html
    while (T--) {
        // Input
        scanf("%s", &line);
        unsigned int board = 0;
        int num = 0;
        for (int i = 0; i < 12; ++i) {
            board <<= 1;
            if (line[i] == 'o') {
                board |= 1;
                ++num;
            }
        }
        // dp: bitmask
        int dp[1<<12] = {0};
        queue<unsigned int> Q;
        int Min = 99;

        Q.push(board);
        dp[board] = num;

        // bfs
        while (!Q.empty()) {
            unsigned int cur = Q.front();
            Min = min(Min, dp[cur]);
            Q.pop();

            for (int i = 0; i < 12; ++i) {
                if (cur & (1<<i)) {
                    if (i>=2 && (cur & (1<<(i-1))) && !(cur & (1<<(i-2)))) {
                        unsigned int nxt = cur;
                        nxt = nxt & (~(1<<i)) & (~(1<<(i-1)));  // unset i and i-1
                        nxt = nxt | (1<<(i-2)); //set i-2
                        dp[nxt] = dp[cur] - 1;
                        Q.push(nxt);
                    }
                    if (i<=9 && (cur & (1<<(i+1))) && !(cur & (1<<(i+2)))) {
                        unsigned int nxt = cur;
                        nxt = nxt & (~(1<<i)) & (~(1<<(i+1)));
                        nxt = nxt | (1<<(i+2));
                        dp[nxt] = dp[cur] - 1;
                        Q.push(nxt);
                    }
                }
            }
        }
        // Output
        printf("%d\n", Min);
    }


X.
int dp(int),map[N],vis[N];
int main()
{
    int n;
    char str[100];
    scanf("%d",&n);
    getchar();
    while(n--)
    {
        memset(map,0,sizeof(map));
        memset(vis,0,sizeof(vis));
        gets(str);
        int len=strlen(str),num=0;
        for(int i=0;i<len;i++)
        {
            if(str[i]=='o') num^=1<<(i);
        }
        printf("%d\n",dp(num));
    }
    return 0;
}
int dp(int x)
{
    if(vis[x]) return map[x];
    else
    {
        int imin=15;
        bool flag=true;
        for(int i=0;i<12;i++)
        {
            if(x&(1<<(i))&&x&(1<<(i+1)))
            {
                if(i>0&&!(x&(1<<(i-1)))) {imin=min(imin,dp(x^(1<<(i-1)^(1<<i)^(1<<(i+1)))));flag=false;}
                if(i+2<12&&!(x&(1<<(i+2)))) {imin=min(imin,dp(x^(1<<i)^(1<<(i+1)^(1<<(i+2)))));flag=false;}

            }
        }
        if(flag)
        {
            int temp=0;
            for(int i=0;i<12;i++)
            {
                if(x&(1<<i)) temp++;
            }
            vis[x]=1;
            map[x]=temp;
            return temp;
        }
        vis[x]=1;
        map[x]=imin;
        return imin;
    }

map<string,int>d;
string str,t;
int n,ans;
int dp(string s)
{
    if(d[s]>0)  return d[s];
    d[s]=1;
    for(int i=0;i<10;i++)
    {
        if(s[i]=='o'&&s[i+1]=='o'&&s[i+2]=='-')
        {
            t=s;
            t[i]=t[i+1]='-';
            t[i+2]='o';
            d[s]=max(d[s],dp(t)+1);
        }
        if(s[i]=='-'&&s[i+1]=='o'&&s[i+2]=='o')
        {
            t=s;
            t[i]='o';
            t[i+1]=t[i+2]='-';
            d[s]=max(d[s],dp(t)+1);
        }
    }
    return d[s];
}

X.
把12个棋位的有无棋子整体看作一个状态,然后宽搜就可以了

DP题,状态总量为2^12,其实可以用对称性减少一半状态数。




Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts