您的位置:首页 > 其它

UVALive - 4327 Parade DP + 优先队列

2015-03-20 21:16 295 查看
题目大意:有n+1条横线,m+1条竖线,你的任务是从最南边的路走到最北边的路,使得走过的路上的高兴值和最大。同一段路不能走超过两次,且不能从北往南走,另外每条横向路上所花的时间不能超过k

解题思路:设dp[i][j]为走到第i条横线,第j条竖线的十字路口的高兴值的最大值

则dp[i][j] = max(dp[i][j], dp[i-1][k] + sum_value[j-1]-sum_value[j][k-1])

然后从左到右扫描更新,再从右到左扫描更新

[code]#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 110
#define maxm 10010
#define INF 0x3f3f3f3f
int sum_len[maxn][maxm], sum_value[maxn][maxm], q[maxm], dp[maxn][maxm], n, m, k;
void DP() {
    int front, rear;
    for(int i = 1; i <= n; i++) {
        front = rear = 0;
        q[0] = 1;
        for(int j = 1; j <= (m+1); j++) {
            while(front <= rear && dp[i-1][q[rear]] - sum_value[i][q[rear]-1] <= dp[i-1][j] - sum_value[i][j-1])
                rear--;
            q[++rear] = j;

            while(front <= rear && sum_len[i][j-1] - sum_len[i][q[front]-1] > k)
                front++;
            dp[i][j] = dp[i-1][q[front]] + sum_value[i][j-1] - sum_value[i][q[front]-1];
        }

        front = rear = 0;
        q[0] = m + 1;
        for(int j = m+1; j >= 1; j--) {
            while(front <= rear && dp[i-1][q[rear]] + sum_value[i][q[rear]-1] <= dp[i-1][j] + sum_value[i][j-1])
                rear--;
            q[++rear] = j;
            while(front <= rear && sum_len[i][q[front]-1] - sum_len[i][j-1] > k)
                front++;
            dp[i][j] = max(dp[i][j],dp[i-1][q[front]] + sum_value[i][q[front]-1]-sum_value[i][j-1]);
        }
    }
}

int main() {
    while(scanf("%d%d%d", &n, &m, &k) == 3 && (n+m+k)) {
        n++;
        int tmp;
        for(int i = 1; i <= n; i++) { sum_value[i][0] = 0; for(int j = 1; j <= m; j++) {
                scanf("%d", &tmp);
                sum_value[i][j] = sum_value[i][j-1] + tmp;
            }
        }

        for(int i = 1; i <= n; i++) {
            sum_len[i][0] = 0;
            for(int j = 1; j <= m; j++) {
                scanf("%d",&tmp);
                sum_len[i][j] = sum_len[i][j-1] + tmp;  
            }
        }
        for(int i = 1; i <= (m+1); i++)
            dp[0][i] =  0;
        DP();
        int ans = -INF;
        for(int i = 1; i <= (m+1); i++)
            ans = max(ans,dp
[i]);
        printf("%d\n",ans);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: