题意:一个国王从矩阵的最下方走到矩阵的最上方(矩阵为n*m,0<n<=100,0<m<=10000),每一个格子是一块街区,每个格子有一定的时间(为正数)
和村民的喜好值(可以为负),国王在东西方向上走的最大距离不能超过k,现在想找到一条路径使得经过街区的喜好值和最大。
题解:简单的队列优化dp,由于街区是格子,所以每层需要设m+1种状态,dp[i][j]代表走到 i 层 j 格子交点(0~m)时的最大值,具体队列维护见代码。
PS:读入需要优化,否则C++会超时,坑了很久唉…
Sure原创,转载请注明出处。
#include <iostream> #include <cstdio> #include <string.h> #define MAX(a , b) ((a) > (b) ? (a) : (b)) using namespace std; const int inf = 1 << 29; const int maxn = 105; const int maxm = 10005; struct node { int pos; int val; }Q[maxm]; int suw[maxn][maxm],sul[maxn][maxm],dp[2][maxm]; char str[2000001]; int k,m,n,wei; int getint() { int data = 0,u = 1; while(str[wei] < '0' || str[wei] > '9' ) wei++; if(wei && str[wei-1]=='-') u = -1; while(str[wei] >= '0' && str[wei] <= '9') { data = data * 10 + str[wei] - '0'; wei++; } return data * u; } void read() { for(int i=n+1;i>=1;i--) { suw[i][0] = 0; gets(str); wei = 0; for(int j=1;j<=m;j++) { suw[i][j] = getint(); suw[i][j] += suw[i][j-1]; } } for(int i=n+1;i>=1;i--) { sul[i][0] = 0; gets(str); wei = 0; for(int j=1;j<=m;j++) { sul[i][j] = getint(); sul[i][j] += sul[i][j-1]; } } return; } void init(int cho,int val) { for(int i=0;i<=m;i++) { dp[cho][i] = val; } return; } void solve() { init(0,0); for(int i=1;i<=n+1;i++) { int cur = i & 1; int pre = cur ^ 1; init(cur,-inf); int head = 0,rear = 0; for(int j=0;j<=m;j++) { int tmp = dp[pre][j] - suw[i][j]; while(head < rear && Q[rear-1].val <= tmp) { rear--; } Q[rear].pos = j; Q[rear++].val = tmp; while(head < rear && sul[i][j] - sul[i][Q[head].pos] > k) { head++; } dp[cur][j] = MAX(dp[cur][j] , Q[head].val + suw[i][j]); } head = rear = 0; for(int j=m;j>=0;j--) { int tmp = dp[pre][j] + suw[i][j]; while(head < rear && Q[rear-1].val <= tmp) { rear--; } Q[rear].pos = j; Q[rear++].val = tmp; while(head < rear && sul[i][Q[head].pos] - sul[i][j] > k) { head++; } dp[cur][j] = MAX(dp[cur][j] , Q[head].val - suw[i][j]); } } int res = -inf; for(int i=0;i<=m;i++) { res = MAX(res , dp[(n+1) & 1][i]); } printf("%d\n",res); return; } int main() { while(gets(str)) { wei = 0; n = getint(); m = getint(); k = getint(); if(n+m+k == 0) break; read(); solve(); } return 0; }