2013-07-07 17:19:57Morris

[UVA][剪枝] 10543 - Traveling Politician

Problem E
Traveling Politician
Time Limit: 2 seconds

A politician from the Alliance of Conservative Monarchists (ACM) is campaigning for the next election. In order to guarantee his victory, he has to make at least k public speeches. He will give one speech every day. If he has to give several speeches in the same city, they cannot be on consecutive days because that would be unproductive. However, the politician believes that giving speech in one day's interval is not useless; for example, giving one speech on Monday and the next one in the same city on Wednesday is alright because after two days, the people will forget about his first speech and his second speech will have as much effect as the first one.

He is absolutely certain that he will win, so at the same time he is moving to the capital. This means that his first speech will be given in his hometown, and his last speech - in the capital city. He knows that his speech-giving abilities deteriorate when he is tired. So he does not want to give more speeches than he has to; k speeches will be enough to win. What is the minimum number of speeches he has to give in order to start in his hometown, end up in the capital and give at least k speeches (Including his speeches in his hometown and in the capital) on the way, without ever giving a speech in the same city on two consecutive days?

Input
The input will consist of several test cases. Each test case will begin with 3 integers on a line - n (the number of cities on the map), m (the number of roads connecting cities) and k (the minimum number of speeches). The next m lines will each contain 2 integers, u and v, meaning that the politician can visit city v immediately after visiting city u. All other routes of travel are infeasible from the point of view of his budget. The politician's hometown is city number 0, and the capital is city number n-1. You can assume that 2<=n<=50 and 2<=k<=16. Input is terminated by a line containing three zeroes.

Output
Print one line per test case, giving the minimum total number of speeches. If this is impossible to do, print "LOSER". See examples. If in a scenario the politician requires to give more than 20 speeches he should be considered a LOSER and so in that case you should print "LOSER" as well.

Sample Input Sample Output
3 3 3
0 1
0 2
1 2
5 6 5
0 1
0 3
1 2
2 4
3 2
3 4
3 3 10
0 1
1 0
1 2
0 0 0
3
LOSER
11


Problemsetter: Igor Naverniouk, special thanks to Shahriar Manzoor


這個人會從家鄉的城鎮出發,在每個經過的點舉行演講,每天將會移動到下一個點。
至少舉行 k 場,最後到達終點,問最少的演講個數為何。
可以在同一個點舉行演講,但不會在連續兩天內在同一個地方,他也許會再去過別的地方時得到新的想法,
下次回來時就會有新的說法。

題目解法:

最常見的就是矩陣乘法,可以計算 k 步從 i->j 的方法數,但是用在這一題消耗量光是矩陣計算就會耗掉 O(50*50*50*k),因為要算最小的 k 步,沒辦法使用分而治之。

因此使用狀態標記,在搜索的時候記錄,到達時的狀態,如果重覆時,那就可以很快地剪枝。
我這裡寫得有點多餘 dp[這一個點][前一個點][此時走了幾步] = 這個狀態是否搜索過。

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int g[50][50] = {}, gt[50];
int used[50][50][22] = {};
int ret;
int N, M, K;
void dfs(int nd, int prev, int depth) {
    if(depth >= K && nd == N-1) {
        ret = min(ret, depth);
        return;
    }
    if(depth >= ret)    return;
    if(used[nd][prev][depth])
        return;
    used[nd][prev][depth] = 1;
    int i;
    for(i = 0; i < gt[nd]; i++) {
        dfs(g[nd][i], nd, depth+1);
    }
}
int main() {
    while(scanf("%d %d %d", &N, &M, &K) == 3 && N) {
        memset(gt, 0, sizeof(gt));
        memset(used, 0, sizeof(used));
        int x, y;
        while(M--) {
            scanf("%d %d", &x, &y);
            g[x][gt[x]++] = y;
        }
        ret = 21;
        dfs(0, 0, 1);
        if(ret == 21)
            puts("LOSER");
        else
            printf("%d\n", ret);
    }
    return 0;
}