2013-06-04 08:24:27Morris

[UVA][dfs、剪枝] 10890 - Maze

Problem D
Maze
Input File: d.in

Output: Standard Output

 

In this problem you are given a square maze of dimension N with N*N blocks. Each block is numbered as follows:

 

N-1, 0

N-1, 1

N-1, N-1

2, 0

2, 1

2, 2

1, 0

1, 1

1, 2

0, 0

0, 1

0, 2

0, N-1

 

 

The maze has only one entry which is at (0, 0) and only one exit which is at (N-1, N-1). From each block you can move in four directions (N, E, W, S) and the cost is 1 for each movement among the maze but collecting treasure does not require any cost.. Some blocks contain treasures that you will have to collect. Suppose there are T treasures in the maze and you have to collect at least S (S T) treasures from them. In this problem, you are requested to find an optimal way from starting location to ending location and take at least S treasures from the maze. Remember that, you can visit a block more than once if you want.

 

Input

The first line of the input contains three integers N (N ≤ 30), T (T ≤ 30) and S (S ≤ 10 and S ≤ T) describing the dimension of the maze, number of treasures in the maze and number of treasures that you can take. After that, there are T lines. Each line contains two numbers representing the position of the treasure in the maze. The input may contain multiple test cases and ends with three zeros for N, T and S.

 

Output

Each test case produces one line of output. This line should contain the output serial no as shown in the sample output and a number representing the minimum cost which is required to collect the treasures.


Sample Input                                 Output for Sample Input

4 4 4

2 0

2 1

2 2

0 2

4 4 2

2 0

2 1

2 2

0 2

0 0 0

 

Case 1: 10

Case 2: 6


Problem setter: Syed Monowar Hossain

Special Thanks: Derek Kisman

寫 A* 沒過,一直 TLE。我想下一次寫的時候,應該先抓一組近似解,然後再跑 A*。
不然 priority_queue 一直吐不出解。

那這題我最後用了 dfs + 減枝。

其實很簡單的,基本上對於點還是按照順序排序比較好,搜索起來比較可以在較早的時間得到解答。
接著就可以在得到解的時候,快速把不可能的解給剪掉。

#include <stdio.h>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
int N, S, T, X[35], Y[35];
int ret, U[35];
void dfs(int nd, int cost, int used) {
    if(cost+(N-X[nd]+N-Y[nd]-2)*1.1 >= ret)
        return;
    if(used == S) {
        ret = min(ret, cost+(N-X[nd]+N-Y[nd]-2));
        return;
    }
    int i;
    for(i = 1; i < T; i++) {
        if(!U[i]) {
            U[i] = 1;
            dfs(i, cost+abs(X[i]-X[nd])+abs(Y[i]-Y[nd]), used+1);
            U[i] = 0;
        }
    }
}
int main() {
    int i, j, cases = 0;
    while(scanf("%d %d %d", &N, &T, &S) == 3) {
        if(N+S+T == 0)
            break;
        int g[35][35] = {};
        for(i = 0; i < T; i++) {
            scanf("%d %d", &X[i], &Y[i]);
            g[X[i]][Y[i]]++;
        }
        X[0] = 0, Y[0] = 0;
        T = 1;
        for(i = 0; i < N; i++) {
            for(j = 0; j < N; j++)
                if(g[i][j])
                    X[T] = i, Y[T] = j, T++;
            U[i] = 0;
        }
        ret = 0xffffff;
        dfs(0, 0, 0);
        printf("Case %d: %d\n", ++cases, ret);
    }
    return 0;
}