UVA 10557 XYZZY

題目

XYZZY

分析

  1. 有這樣的一個遊戲,遊戲中有許多房間,開始時主角擁有100的體力,每進入一個房間都會消耗或增加房間對應的體力值,同時每個房間的出口不唯一,如果在到達最後一個房間前體力歸零,GAME OVER && YOU LOST
  2. 顯然主角應該儘可能地避免走入會消耗體力值的房間,如果無法避開,那麼主角要有足夠的體力值纔可以嘗試進入,可以發現如果有這麼一個路連通兩個或者多個房間能夠不斷恢復體力,那麼可以意味着主角可以隨意地 到任一房間也無妨,那麼如果有並且能到達終點,勝利在望啊。
  3. 也就是說,對於連接房間()的路(),如果能夠找到一個回覆點(正環)且能夠到達終點(可達)即可以判定勝利,如果找不到但是到達終點時仍有體力值,那麼也可以判定爲勝利。以外的情況均判定爲失敗

思路

  1. 首先考慮可達的問題,對於一張圖,可以用鄰接矩陣表示,也就是可以利用floyd_warshall()方法求其可達性矩陣,即可以判斷兩點是否可達。
  2. 舉一個例子來意會一下bellman_ford()。對每一個點遍歷一次邊,鬆弛對應的權值的上界來滿足經過該點時需要的負權。

5
0 1 2
20 2 1 3
-60 1 4
-60 1 5
0 0

那麼它有這樣五條邊

(1 + 0)
1-> 2 +20
2 -> 1 +0
2 -> 3 -60
3 -> 4 -60
4 -> 5(終點) +0

鬆弛的結果如下

120 120 60 -100000000 -100000000
140 140 80 20 20
160 160 100 40 40
180 180 120 60 60
(+0)(+20)(-60)(-60)(+0)

樣例

INPUT

4
0 1 2
-100 1 3
1 1 4
0 0
-1

OUTPUT

hopeless

代碼

#include <cstdio>
#include <cstring>
#define MAX_V 105
#define MAX_E MAX_V*MAX_V
#define INF 100000000

int A[MAX_V][MAX_V], d[MAX_V], cost[MAX_V];
int V, E;
struct edge { int from, to; } es[MAX_E], e;

void input()
{
    E = 0;
    memset(A, 0, sizeof(A));
    int n = 0, t = 0;
    for (int i = 1; i <= V; i++) {
        scanf("%d%d", &cost[i], &n);
        while (n--) {
            scanf("%d", &t);
            A[i][t] = 1; es[E].from = i; es[E].to = t; E++;
        }
    }
}

void floyd_warshall()
{
    for (int k = 1; k <= V; k++)
        for (int i = 1; i <= V; i++)
            for (int j = 1; j <= V; j++)
                A[i][j] = A[i][j] | (A[i][k] & A[k][j]);
}

bool bellman_ford()
{
    for (int i = 1; i <= V; i++) d[i] = -INF;
    d[1] = 100;
    for (int i = 1; i < V; i++)
        for (int j = 0; j < E; j++) {
            e = es[j];
            if (d[e.to] < d[e.from] + cost[e.to] && d[e.from] + cost[e.to] > 0)
                d[e.to] = d[e.from] + cost[e.to];
        }
    for (int i = 0; i < E; i++) {
        e = es[i];
        if (d[e.to] < d[e.from] + cost[e.to] && d[e.from] + cost[e.to] > 0)
            if (A[e.to][V]) return true;
    }
    return d[V] > 0;
}

void solve()
{
    floyd_warshall();
    if (bellman_ford()) printf("winnable\n");
    else printf("hopeless\n");
}

int main()
{
    while (scanf("%d", &V), V != -1) {
        input();
        solve();
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章