领土划分
问题描述
著名的女王,阳姐•查兰•伊丽莎白一世有两个宠物,一个叫大黄,一个叫小昊。
女王赐予了这两个宠物一份
N∗M
的土地。
这片土地由
N∗M
个长度为一单位的小正方形构成,每一个小正方形种植水稻或者小麦,但种植的量可能不同。
大黄喜欢吃饭,也就是说,他希望他的领地里的水稻种植量多,类似的,小昊喜欢吃面,所以他希望他的领地里的小麦种植量多。
为了这片土地的划分,大黄与小昊经常发生狗咬狗、相煎何太急的惨剧。
现在女王决定,派出一辆推土机,这辆推土机从左上角开始,每次向右向下或者向右下移动一个格子,直到走到土地的右下角为止,推土机经过的格子将变为废墟。
这样就会将土地分成上下两块,其中右上的那一块归小昊,左下的那一块归大黄。
现在女王想知道,这辆推土机如何移动,能够使得大黄领地中水稻种植总量和小昊领地中小麦种植总量之和最大?
输入
输入文件名为Divide.in。
输入第一行包含两个正整数
N
和
下接一个
N∗M
的矩阵描述这块土地的信息,其中,每个格子的信息按照如下方式表示:若该格子种的是水稻,则形式为“JX”,其中
X
为该格子中水稻的种植量;若该格子种的是小麦,则形式为“KX”,其中
保证种植量均为小于等于
99
的非负整数,且每一行中相邻两个格子之间有逗号隔开。
输出
输出文件名为Divide.out。
输出第一行包含一个正整数,为可能的最大的两种作物种植量总和。
输入样例
4 3
K2 K3 K5
J3 K1 J1
J2 J4 K1
K1 K3 J3
输出样例
17
样例解释
移动方法为向右下,向右下,向下。总和为 (3+2+4)+(3+5)=17 。
数据范围
40%
的数据保证
1<=N,M<=100
。
100%
的数据保证
1<=N,M<=1500
。数据保证有梯度。
Solution
设
fi,j
表示当前在
(i,j)
,而接下来的路线是一直向右,到达边界后一直向下的最大值(奇葩的状态表示,就我想的出来)。
首先,当前位置可以是从左边走过来的。若是从左边走过来的,则
fi,j=fi,j−1
其次,当前位置也可以是从上边走过来的。若是从上边走过来的,则
fi,j=fi−1,j+(i−1,j+1)
到
(i−1,m)
一段小麦的和
−(i,j)
到
(i,m−1)
一段水稻的和。
从左上走过来的同理。
Code
#include <iostream>
#include <cstdio>
#include <cstring>
#define Max(x,y) ((x)>(y)?(x):(y))
using namespace std;
int n,m;
int MI[1510][1510],DA[1510][1510];
int f[1510][1510];
char str[100000];
int main(){
freopen("divide.in","r",stdin);
freopen("divide.out","w",stdout);
memset(f,-1,sizeof f);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
char ch;int num=0,q=1;
scanf("%s",str);
ch=str[0];
while(str[q]<'0'||str[q]>'9')q++;
while(str[q]>='0'&&str[q]<='9'){num=num*10+str[q]-'0';q++;}
if(ch=='K'){
MI[i][j]=MI[i-1][j]+MI[i][j-1]-MI[i-1][j-1]+num;
DA[i][j]=DA[i-1][j]+DA[i][j-1]-DA[i-1][j-1];
}
else{
MI[i][j]=MI[i-1][j]+MI[i][j-1]-MI[i-1][j-1];
DA[i][j]=DA[i-1][j]+DA[i][j-1]-DA[i-1][j-1]+num;
}
}
if(n==1||m==1){
printf("0\n");
return 0;
}
for(int i=1;i<=m;i++){
f[1][i]=DA[n][m-1]-DA[1][m-1];
}
for(int i=2;i<=n;i++){
for(int j=1;j<=m;j++){
f[i][j]=f[i][j-1];
f[i][j]=Max(f[i][j],f[i-1][j]+MI[i-1][m]-MI[i-1][j]-MI[i-2][m]+MI[i-2][j]-(DA[i][m-1]-DA[i][j-1]-DA[i-1][m-1]+DA[i-1][j-1]));
if(j-1!=0){
f[i][j]=Max(f[i][j],f[i-1][j-1]+MI[i-1][m]-MI[i-1][j-1]-MI[i-2][m]+MI[i-2][j-1]-(DA[i][m-1]-DA[i][j-1]-DA[i-1][m-1]+DA[i-1][j-1]));
}
}
}
printf("%d\n",f[n][m]);
return 0;
}