24h購物| | PChome| 登入
2013-04-19 20:44:45| 人氣1,090| 回應1 | 上一篇 | 下一篇

[UVA][dp] 10888 - Warehouse

推薦 0 收藏 0 轉貼0 訂閱站台

Problem B
Warehouse
Input: Standard Input

Output: Standard Output

 

A number of boxes is to be moved in a warehouse. The warehouse can be modeled as a grid where each square is the equal to the size of a box. Consider the model below: (‘B’ = box to be moved, ‘.’ = empty square, ‘X’ = position a box should occupy after the move, ‘#’ = obstacle)

 
BBBB....
.###...X
.XX#...X
...#....
........

A box may be moved to any of its four neighboring squares, assuming this square is empty (that is, not occupied by another box or an obstacle). To move a box takes one unit of time, and only one box may be moved per time unit. Your task is to determine the least amount of time to move all boxes to their destination squares. You may assume that a solution exists. Number of boxes will be no more than 15.

Input

The first line in the input contains the number of test cases (at most 20). Each case starts with a line containing two integers, the height (1 ≤ h ≤ 40) and width (1 ≤ w ≤ 40) of the grid. Then follows h lines, each containing w characters, describing the grid in the format above.

 

Output

For each test case, output a line containing a single integer: the minimum number of time units to move all boxes.

 

Sample Input                               Output for Sample Input

1
5 8
BBBB....
.###...X
.XX#...X
...#....
........
 

20


Problem setter: Jimmy Mårdell

Special Thanks: Mohammad Sajjad Hossain

test case:
5
5 8
BBBB....
.###...X
.XX#...X
...#....
........
5 8
....#...
....#...
B..X#B.X
....#...
....#...

題目簡單地要求二分圖匹配權重總合最小。

位元的狀態壓縮,把已經匹配過的點當做1, 沒有則0, 因此最多 15 bits。

dp 的方法:

依序放入X團的點,然後Y團匹配過的會變成一個狀態,從狀態中沒被匹配過的點進行鬆弛。

#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
int ng[50][50], used[50][50];
int dp[1<<16], W[30][30];
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
int Bt, Xt, n, m;
char g[50][50];
void bfs(int x, int y) {
    memset(used, 0, sizeof(used));
    int i, tx, ty;
    queue<int> X, Y;
    X.push(x), Y.push(y);
    while(!X.empty()) {
        x = X.front(), X.pop();
        y = Y.front(), Y.pop();
        if(g[x][y] == 'X')
            W[Bt][ng[x][y]] = used[x][y];
        for(i = 0; i < 4; i++) {
            tx = x+dx[i], ty = y+dy[i];
            if(tx < 0 || tx >= n || ty < 0 || ty >= m)
                continue;
            if(g[tx][ty] == '#')
                continue;
            if(used[tx][ty] == 0) {
                used[tx][ty] = used[x][y]+1;
                X.push(tx);
                Y.push(ty);
            }
        }
    }
}
int main() {
    int t, i, j, k;
    scanf("%d", &t);
    while(t--) {
        scanf("%d %d", &n, &m);
        for(i = 0; i < n; i++)
            scanf("%s", g[i]);
        Bt = 0, Xt = 0;
        for(i = 0; i < n; i++)
            for(j = 0; j < m; j++)
                if(g[i][j] == 'X')
                    ng[i][j] = Xt++;
        for(i = 0; i <= Xt; i++)
            for(j = 0; j <= Xt; j++)
                W[i][j] = 1<<20;
        for(i = 0; i < n; i++) {
            for(j = 0; j < m; j++) {
                if(g[i][j] == 'B') {
                    Bt++;
                    bfs(i, j);
                }
            }
        }
        int mxState = (1<<Xt);
        for(i = 0; i < mxState; i++)
            dp[i] = 1<<20;
        dp[0] = 0;
        vector<int> DIGIT[16];
        for(i = 0; i < mxState; i++) {
            j = __builtin_popcount(i);
            DIGIT[j].push_back(i);
        }
        for(i = 1; i <= Bt; i++) {
            for(int k1 = 0; k1 < DIGIT[i-1].size(); k1++) {
                j = DIGIT[i-1][k1];
                for(k = 0; k < Bt; k++) {
                    if((j&(1<<k)) == 0) {
                        dp[j|(1<<k)] = min(dp[j|(1<<k)], dp[j]+W[i][k]);
                    }
                }
            }
        }
        printf("%d\n", dp[mxState-1]);
    }
    return 0;
}
/*
5
5 8
BBBB....
.###...X
.XX#...X
...#....
........
5 8
....#...
....#...
B..X#B.X
....#...
....#...
*/

台長: Morris
人氣(1,090) | 回應(1)| 推薦 (0)| 收藏 (0)| 轉寄
全站分類: 不分類 | 個人分類: UVA |
此分類下一篇:[UVA][窮舉] 10001 - Garden of Eden
此分類上一篇:[UVA][數學、N皇后單一快速解] 10094 - Place the Guards

s89162504
這題有可能'X'的數目允許比'B'的數目多嗎?
2013-04-23 11:06:25
版主回應
一定會相等,討論區有提到,作者忘記加上去。
不然最好使用 min-cost-maxflow, 最少費用流。
2013-04-23 11:36:03
是 (若未登入"個人新聞台帳號"則看不到回覆唷!)
* 請輸入識別碼:
請輸入圖片中算式的結果(可能為0) 
(有*為必填)
TOP
詳全文