【問題描述】
某旅遊景區的街道成網格狀。其中東西向的街道都是旅遊街,南北向的街道都是林蔭道。由於遊客衆多,旅遊街規定爲單行道,遊客在旅遊街上只能從西向東走,在林蔭道上則既可從南向北,又可從北向南走。
阿龍想到這個旅遊街區遊玩。他的好友阿福給了他一些建議,用分值表示所有旅遊街相鄰兩個路口之間的街道值得遊覽程度,分值是從-100到100的整數,所有林蔭道不打分。所有分值不能全是負分。
如下圖,是被打過分的某旅遊的街道圖:
阿龍可以從任何一個路口開始遊覽,在任何一個路口結束遊覽。請你寫一個程序,幫助阿龍找一條最佳的旅遊路線,使得這條路線的所有分值總和最大。
【輸入格式】
第一行是兩個整數m和n,之間用一個空格分開,m表示有多少條旅遊街,n表示有多少條林蔭道。接下來的m行一次給出了由北向南每條旅遊街的分值。每行有n個整數,一次表示自西向東旅遊街每一小段的分值。同一行相鄰兩個數之間用一個空格隔開。
【輸出格式】
一行一個整數,表示最佳旅遊路線的最大總分值。
【輸入樣例】
3 6
-50 -47 36 -30 -23
17 -19 -34 -13 -8
-42 -3 -43 34 -45
【輸出樣例】
84
【樣例解釋】
沿着如下圖的路線走是最優路線:
【數據範圍】
1<=m<=100 1<=n<=20001
【來源】
NOI1994
【思路梳理】
簡單的水題,先貪心地排序,再動態規劃即可順利解決。將每一列的所有數值按從小到大的順序排個序(筆者用的是二維的優先隊列),保證經過這一列的旅遊街時,該旅遊街的分數儘可能的大,然後再動態規劃依次求出經過各列旅遊街所能夠得到的最大打分就可以。
d[i]=從第一列的旅遊街走到第i列的旅遊街所能夠得到的最大分數。
狀態轉移方程:d[j]=max(d[j],d[j-1]+d[j][i])。
【Cpp代碼】
#include<cstdio>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#define maxn 20005
using namespace std;
int n,m,d[maxn];
struct cmp1
{
bool operator()(int a,int b)
{
return a<b;
}
};
priority_queue<int,vector<int>,cmp1>q[maxn];
bool cmp(int a,int b)
{
return a>b;
}
void solve()
{
for(int i=1;i<=n;i++)
d[i]=max(d[i],d[i-1]+q[i].top());
int ans=0;
for(int i=1;i<=n;i++) ans=max(ans,d[i]);
cout<<ans;
}
int main()
{
// freopen("in.txt","r",stdin);
cin>>m>>n;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
{
int x;
scanf("%d",&x);
q[j].push(x);
}
solve();
return 0;
}