题目描述:
【题意】 在 N*M 的矩阵中,每个格子有一个权值,要求寻找一个包含 K 个格子的凸连通块(连通块中间没有空缺,并且轮廓是凸的),使这个连通块中的格子的权值和最大。
注意:凸连通块是指:连续的若干行,每行的左端点列号先递减、后递增,右端点列号先递增、后递减。 求出这个最大的权值和,并给出连通块的具体方案,输出任意一种方案即可。 【输入格式】 第一行包含三个整数N,M和K。 接下来N行每行M个整数,表示N*M的矩阵上每个格子的权值(均不超过1000)。 【数据范围】 1<=n,m<=15 【输入样例】 2 3 4 10 20 30 40 2 3 【输出样例】 Oil : 100 1 1 1 2 1 3 2 1
抓住问题的本质,每行的左端点列号先递减、后递增,右端点列号先递增、后递减。虽然这显然不是凸连通块的定义,(比如十字架也满足这个条件,但是它不是凸连通块)但既然出题人的数学没有学好,我们就将错就错了这里还有个小错误,就是如果最后的答案只有一行的点的话,就可能没有记录。因为代码已经太长我懒得再写了,而且我估计没有这样的数据点(事实证明我是对的),当然补上也不难
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; inline int read() { char c=getchar();int f=1,s=0; while(!isdigit(c)){if(c=='-')f=-1;c=getchar();} while(isdigit(c)){s=s*10+c-'0';c=getchar();} return f*s; } int n,m,k; int f[16][250][16][16][2][2],a[16][16],sum[16][16]; struct node { int l,r,x,y; // node(int ll=0,int rr=0,int xx=0,int yy=0){l=ll;r=rr;x=xx;y=yy;} }d[16][250][16][16][2][2]; struct putout { int i,j,l,r,x,y,d; // putout(int ii=0,int jj=0,int ll=0,int rr=0,int xx=0,int yy=0,int dd=0){i=ii;j=jj;l=ll;r=rr;x=xx;y=yy;d=dd;} }ans; inline int mymin(int x,int y){return x<y?x:y;} inline int mymax(int x,int y){return x>y?x:y;} int main() { n=read();m=read();k=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=read(),sum[i][j]=sum[i][j-1]+a[i][j]; ans.d=0; for(int i=1;i<=n;i++)//当前进行到第几行 { for(int j=1;j<=mymin(i*m,k);j++)//当前一共选了多少个 { for(int l=1;l<=m;l++) { for(int r=l;r<=mymin(m,l+j-1);r++) { int snow=sum[i][r]-sum[i][l-1]; if(r-l+1>j)break; if(snow>f[i][j][l][r][0][0]) { f[i][j][l][r][0][0]=snow; d[i][j][l][r][0][0]={0,0,-1,-1}; } if(snow>f[i][j][l][r][0][1]) { f[i][j][l][r][0][1]=snow; d[i][j][l][r][0][1]={0,0,-1,-1}; } if(snow>f[i][j][l][r][1][0]) { f[i][j][l][r][1][0]=snow; d[i][j][l][r][1][0]={0,0,-1,-1}; } if(snow>f[i][j][l][r][1][1]) { f[i][j][l][r][1][1]=snow; d[i][j][l][r][1][1]={0,0,-1,-1}; } if(i==1)continue; //x=0,y=1; { for(int p=l;p<=r;p++) { for(int q=p;q<=r;q++) { if(q-p+1+r-l+1>j)break; if(f[i-1][j-(r-l+1)][p][q][0][1]+snow>f[i][j][l][r][0][1]) { f[i][j][l][r][0][1]=f[i-1][j-(r-l+1)][p][q][0][1]+snow; d[i][j][l][r][0][1]={p,q,0,1}; } if(f[i][j][l][r][0][1]>ans.d) ans={i,j,l,r,0,1,f[i][j][l][r][0][1]}; } } } //x=1,y=0; { for(int p=l;p>=1;p--) { if(r-p+1+r-l+1>j)break; for(int q=r;q<=m;q++) { if(q-p+1+r-l+1>j)break; if(f[i-1][j-(r-l+1)][p][q][1][0]+snow>f[i][j][l][r][1][0]) { f[i][j][l][r][1][0]=f[i-1][j-(r-l+1)][p][q][1][0]+snow; d[i][j][l][r][1][0]={p,q,1,0}; } if(f[i-1][j-(r-l+1)][p][q][1][1]+snow>f[i][j][l][r][1][0]) { f[i][j][l][r][1][0]=f[i-1][j-(r-l+1)][p][q][1][1]+snow; d[i][j][l][r][1][0]={p,q,1,1}; } if(f[i-1][j-(r-l+1)][p][q][0][0]+snow>f[i][j][l][r][1][0]) { f[i][j][l][r][1][0]=f[i-1][j-(r-l+1)][p][q][0][0]+snow; d[i][j][l][r][1][0]={p,q,0,0}; } if(f[i-1][j-(r-l+1)][p][q][0][1]+snow>f[i][j][l][r][1][0]) { f[i][j][l][r][1][0]=f[i-1][j-(r-l+1)][p][q][0][1]+snow; d[i][j][l][r][1][0]={p,q,0,1}; } if(f[i][j][l][r][1][0]>ans.d) ans={i,j,l,r,1,0,f[i][j][l][r][1][0]}; } } } //x=0,y=0; { for(int p=l;p<=r;p++) { for(int q=r;q<=m;q++) { if(q-p+1+r-l+1>j)break; if(f[i-1][j-(r-l+1)][p][q][0][0]+snow>f[i][j][l][r][0][0]) { f[i][j][l][r][0][0]=f[i-1][j-(r-l+1)][p][q][0][0]+snow; d[i][j][l][r][0][0]={p,q,0,0}; } if(f[i-1][j-(r-l+1)][p][q][0][1]+snow>f[i][j][l][r][0][0]) { f[i][j][l][r][0][0]=f[i-1][j-(r-l+1)][p][q][0][1]+snow; d[i][j][l][r][0][0]={p,q,0,1}; } if(f[i][j][l][r][0][0]>ans.d) ans={i,j,l,r,0,0,f[i][j][l][r][0][0]}; } } } //x=1,y=1; { for(int p=l;p>=1;p--) { for(int q=r;q>=l;q--) { if(q-p+1+r-l+1>j)break; if(f[i-1][j-(r-l+1)][p][q][1][1]+snow>f[i][j][l][r][1][1]) { f[i][j][l][r][1][1]=f[i-1][j-(r-l+1)][p][q][1][1]+snow; d[i][j][l][r][1][1]={p,q,1,1}; } if(f[i-1][j-(r-l+1)][p][q][0][1]+snow>f[i][j][l][r][1][1]) { f[i][j][l][r][1][1]=f[i-1][j-(r-l+1)][p][q][0][1]+snow; d[i][j][l][r][1][1]={p,q,0,1}; } if(f[i][j][l][r][1][1]>ans.d) ans={i,j,l,r,1,1,f[i][j][l][r][1][1]}; } } } } } } } printf("Oil : %d\n",ans.d); int i=ans.i,j=ans.j,l=ans.l,r=ans.r,x=ans.x,y=ans.y; while(i && x!=-1 && y!=-1) { for(int tt=l;tt<=r;tt++)printf("%d %d\n",i,tt); int ll,rr,xx,yy; ll=d[i][j][l][r][x][y].l; rr=d[i][j][l][r][x][y].r; xx=d[i][j][l][r][x][y].x; yy=d[i][j][l][r][x][y].y; i--;j-=(r-l+1); l=ll;r=rr;x=xx;y=yy; } return 0; }