心中报情
jzoj 2317
题目大意:
在一个n*m矩阵中,有k个选定的子矩阵,每个矩阵有一个代价,现在让你选两个子矩阵(有相交的),使他们覆盖的元素之和减去他两的代价最大(重复的只算一次)
输入样例#1:
3 3 3
2 1 -1
-1 0 1
1 -2 1
2 1 3 2 -1
1 1 3 3 2
1 1 1 1 0
输出样例#1:
1
输入样例#2:
1 2 2
0 0
1 1 1 1 0
1 2 1 2 0
输出样例#2:
F
解题思路:
直接暴力枚举所有子矩阵即可
代码:
#include<cstdio>
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
using namespace std;
long long n,m,k,x0,x1,y0,y1,s1,s2,s3,ans,c[1500],x[5][1500],y[5][1500],f[1500][1500];
int read()
{char x=getchar();long long d=1,o=0;while (x<'0'||x>'9') {if (x=='-') d=-1;x=getchar();}while (x>='0'&&x<='9') o=(o<<3)+(o<<1)+x-48,x=getchar();return d*o;
}
int main()
{ans=-1152921504606846976;n=read();m=read();k=read();for (int i=1;i<=n;++i)for (int j=1;j<=m;++j)f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+read();for (int i=1;i<=k;++i)x[0][i]=read(),y[0][i]=read(),x[1][i]=read(),y[1][i]=read(),c[i]=read();for (int i=1;i<=k;++i)for (int j=i+1;j<=k;++j){x0=max(x[0][i],x[0][j]);//求相交部分x1=min(x[1][i],x[1][j]);y0=max(y[0][i],y[0][j]);y1=min(y[1][i],y[1][j]);if (x0<=x1&&y0<=y1)//判断是否相交{s1=f[x[1][i]][y[1][i]]-f[x[0][i]-1][y[1][i]]-f[x[1][i]][y[0][i]-1]+f[x[0][i]-1][y[0][i]-1];//第一个矩阵s2=f[x[1][j]][y[1][j]]-f[x[0][j]-1][y[1][j]]-f[x[1][j]][y[0][j]-1]+f[x[0][j]-1][y[0][j]-1];//第二个矩阵s3=f[x1][y1]-f[x0-1][y1]-f[x1][y0-1]+f[x0-1][y0-1];//相交部分ans=max(ans,s1+s2-s3-c[i]-c[j]);}}if (ans==-1152921504606846976) printf("F");else printf("%lld",ans);return 0;
}