24h購物| | PChome| 登入
2013-05-24 08:29:13| 人氣371| 回應0 | 上一篇 | 下一篇

[UVA][爛解][spfa更新] 10913 - Walking on a Grid

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

4th IIUC Inter-University Programming Contest, 2005

I

Walking on a Grid

Input: standard input
Output: standard output

Problemsetter: Sohel Hafiz

You will be given a square grid of size N × N. The top-left square has a coordinate of (1, 1) and that of bottom-right is (N, N). Your job is to walk from (1, 1) to (N, N). Very easy, right? That’s why you have to follow some rules when walking.

  1. You can only move left, right or down.
  2. (i, j-1) is left of (i, j), (i, j+1) is right of (i, j) and (i+1, j) is down of (i, j).
  3. You can never move outside the grid.
  4. You can not step on a cell more than once.
  5. Every cell has an integer associated with it.
  6. You have to make sure the sum of integers of the path is maximized.
  7. You can step on at most k negative integers from source to destination.

Input

Each case will start with two integers N and k. N ≤ 75 and k ≤ 5. Each of the next N lines will contain N integers each given in row major order. That is, the first integer of the first row is (1, 1) and the last integer of last row is (N, N). Input terminates with two zeros on a line.

Output

For every case output the case number. If it’s not possible to reach the destination meeting the above rules then output “impossible”, else print the maximum sum of integers of the path.

Sample Input

Output for Sample Input

4 1
1 2 3 -5
-10 6 0 -1
-10 -10 -10 2
0 0 0 1
4 0
1 2 3 -5
-10 6 0 -1
-10 -10 -10 2
0 0 0 1
0 0

Case 1: 11
Case 2: impossible



題目描述:
從左上角點走到右下角點,其路徑過成功的總合要越大越好。
其限制最多(含)經過 k 個負數,而且不同重複經過同一個點,走的方向有往下、左、右。

題目解法:

如果將每個點畫分成三個狀態(上一次從哪裡來),進行轉移的話,圖是個 DAG,不斷地進行更新就好。

dp[node_x][node_y][negtive_used][prev_dir] = maximum result.

照理來講應該要用記憶化搜索的 dp 去解會比較好,有點懶了,用 spfa 跑刷新。
因此 ... 很慢。

#include <stdio.h>
#include <queue>
using namespace std;
int N, K;
int dp[80][80][10][3];//up, left, right
int inq[80][80][10][3];
int g[80][80];
void spfa() {
    int i, j, k, l;
    for(i = 0; i < N; i++) {
        for(j = 0; j < N; j++) {
            for(k = 0; k <= K; k++) {
                for(l = 0; l < 3; l++)
                    dp[i][j][k][l] = -0xfffffff;
            }
        }
    }
    queue<int> X, Y, NEG, DIR;
    int x, y, neg, dir;
    int tx, ty, tneg, tdir;
    X.push(0), Y.push(0), NEG.push(g[0][0] < 0), DIR.push(0);
    dp[0][0][g[0][0] < 0][0] = g[0][0];
    while(!X.empty()) {
        x = X.front(), X.pop();
        y = Y.front(), Y.pop();
        neg = NEG.front(), NEG.pop();
        dir = DIR.front(), DIR.pop();
        inq[x][y][neg][dir] = 0;
        tx = x, ty = y-1, tdir = 1, tneg = neg;
        if(dir != 2 && ty >= 0) { // left
            if(g[tx][ty] < 0)   tneg = neg+1;
            if(tneg <= K && dp[tx][ty][tneg][tdir] < dp[x][y][neg][dir]+g[tx][ty]) {
                dp[tx][ty][tneg][tdir] = dp[x][y][neg][dir]+g[tx][ty];
                if(inq[tx][ty][tneg][tdir] == 0) {
                    inq[tx][ty][tneg][tdir] = 1;
                    X.push(tx), Y.push(ty), NEG.push(tneg), DIR.push(tdir);
                }
            }
        }
        tx = x, ty = y+1, tdir = 2, tneg = neg;
        if(dir != 1 && ty < N) { // right
            if(g[tx][ty] < 0)   tneg = neg+1;
            if(tneg <= K && dp[tx][ty][tneg][tdir] < dp[x][y][neg][dir]+g[tx][ty]) {
                dp[tx][ty][tneg][tdir] = dp[x][y][neg][dir]+g[tx][ty];
                if(inq[tx][ty][tneg][tdir] == 0) {
                    inq[tx][ty][tneg][tdir] = 1;
                    X.push(tx), Y.push(ty), NEG.push(tneg), DIR.push(tdir);
                }
            }
        }
        tx = x+1, ty = y, tdir = 0, tneg = neg;
        if(tx < N) { // up
            if(g[tx][ty] < 0)   tneg = neg+1;
            if(tneg <= K && dp[tx][ty][tneg][tdir] < dp[x][y][neg][dir]+g[tx][ty]) {
                dp[tx][ty][tneg][tdir] = dp[x][y][neg][dir]+g[tx][ty];
                if(inq[tx][ty][tneg][tdir] == 0) {
                    inq[tx][ty][tneg][tdir] = 1;
                    X.push(tx), Y.push(ty), NEG.push(tneg), DIR.push(tdir);
                }
            }
        }
    }
    int ret = -0xfffffff;
    for(i = 0; i <= K; i++)
        for(j = 0;j < 3; j++)
            ret = max(ret, dp[N-1][N-1][i][j]);
    if(ret != -0xfffffff)
        printf("%d\n", ret);
    else
        puts("impossible");
}
int main() {
    int i, j, cases = 0;
    while(scanf("%d %d", &N, &K) == 2) {
        if(N == 0)
            break;
        for(i = 0; i < N; i++)
            for(j = 0; j < N; j++)
                scanf("%d", &g[i][j]);
        printf("Case %d: ", ++cases);
        spfa();
    }
    return 0;
}

台長: Morris
人氣(371) | 回應(0)| 推薦 (0)| 收藏 (0)| 轉寄
全站分類: 不分類 | 個人分類: UVA |
此分類下一篇:[UVA][dp] 10721 - Bar Codes
此分類上一篇:[UVA][SCC] 1263 - Mines

是 (若未登入"個人新聞台帳號"則看不到回覆唷!)
* 請輸入識別碼:
請輸入圖片中算式的結果(可能為0) 
(有*為必填)
TOP
詳全文