Description
ztxz16如愿成为码农之后,整天的生活除了写程序还是写程序,十分苦逼。终于有一天,他意识到自己的生活太过平淡,于是决定外出旅游丰富阅历。
ztxz16生活的城市有NM个景点,可以描述成一个NM的矩形,每个景点有一个坐标(x, y) (1 <= x <= N, 1 <= y <= M)以及美观度A[x][y]和观赏所需的时间B[x][y],从一个景点(x1, y1)走到另一个景点(x2, y2)需要时间为它们之间的曼哈顿距离:|x1 - x2| +|y1 - y2|。
为了防止审美疲劳,ztxz16希望观赏的景点的的美观度是严格上升的,由于不想太早回家码代码,ztxz16希望旅游的总时间尽可能长。
Input
第一行输入两个整数N, M;
接下来N行每行M个整数,第x行第y个整数代表A[x][y];
接下来N行每行M个整数,第x行第y个整数代表B[x][y];
注意,有一些A[x][y]=B[x][y]=0,说明这个景点已经拆除,不能游览;
Output
输出一行代表最长的总时间。
Sample Input
4 5
1 2 6 0 2
1 3 4 0 4
0 0 4 0 3
2 2 0 0 4
1 3 5 0 2
2 8 1 0 2
0 0 3 0 4
0 5 0 0 3
Sample Output
39
【样例说明】
游览顺序为(2,1)->(1,5)->(2,2)->(4,5)->(1,3)
Data Constraint
对于30%的数据:1<=N<=50 , 1<=M<=50
对于60%的数据:1<=N<=300 , 1<=M<=300
对于100%的数据:1<=N<=1000 , 1<=M<=1000
0<=A[x][y]<=1000000
0<=B[x][y]<=10^9
注意:本题输入数据较大,请注意输入消耗的时间
//written by zzy
题目大意:
求给你两个n*m的矩阵,a表优美度,b表时间,两点之间的时间为曼哈顿距离,求走优美度上升的最大时间。
题解:
dp,易推方程,将矩阵拆成n*m个点,按a值从小到大排序,设f[i]表到点i的最长时间,
f[i]=max{f[j]+b[xi,yi]+abs(xi-xj)+abs(yi-yj)}
注意细节,ai,j=bi,j=0时不能作为起点
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define N 1005
#define Max 999999997
using namespace std;
long long i,j,k,n,m,l,ki,kj,xi,xj,yi,yj,s,ans;
long long head,tail;
long long x[N*N],y[N*N],b[N][N],f[N*N];
struct E {
long long num,a;
}p[N*N];
bool cmp(E xx,E yy)
{
return xx.a<yy.a;
}
void read()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
l++; p[l].num=l;
x[l]=i; y[l]=j;
scanf("%lld",&p[l].a);
}
l=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
l++;
scanf("%lld",&b[i][j]);
if (p[l].a==b[i][j]&&b[i][j]==0)
p[l].a=-Max;
}
}
int main()
{
read();
sort(p+1,p+l+1,cmp);
head=1;
while (p[head].a==-Max) head++;
tail=head;
while (p[head].a==p[tail].a) {
ki=p[tail].num;
xi=x[ki]; yi=y[ki];
f[tail]+=b[xi][yi];
tail++;
}
for (i=tail;i<=l;i++)
for (j=head;j<=tail-1;j++)
{
if (p[tail].a!=p[i].a) {
head=tail; tail=i;
}
ki=p[i].num; kj=p[j].num;
xi=x[ki]; yi=y[ki];
xj=x[kj]; yj=y[kj];
s=abs(xi-xj)+abs(yi-yj);
f[i]=max(f[i],f[j]+b[xi][yi]+s);
}
for (i=1;i<=l;i++)
ans=max(ans,f[i]);
printf("%lld",ans);
}