CH5104 & AcWing276 I-country
令 \(f(c,l,r,k,0/1,0/1)\) 表示第 \(c\) 列选第 \(l\sim r\) 行,总共选了 \(k\) 个格子,状态为 \((0/1,0/1)\) 时的答案,其中第一个 \(0/1\) 表示凸多边形上面的边在扩张/收缩,第二个 \(0/1\) 表示凸多边形下面的边在收缩/扩张,然后暴力转移即可。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=15;
int dp[N+10][N+10][N+10][N*N+10][2][2]; // dp[column][left][right][k][0/1][0/1]
// 0 1
//上 / \
//下 \ /
int a[N+10][N+10],sum[N+10][N+10];
struct Pre
{
int c,l,r,d;
bool p1,p2;
Pre() {}
Pre(int cc,int ll,int rr,int dd,bool pp1,bool pp2)
{
c=cc;l=ll;r=rr;d=dd;
p1=pp1;p2=pp2;
}
}pre[N+10][N+10][N+10][N*N+10][2][2],Ans;
void Print(int c,int l,int r,int d,bool p1,bool p2)
{
if(d==0) return;
for(int i=l;i<=r;i++) printf("\n%d %d ",i,c);
Pre p=pre[c][l][r][d][p1][p2];
Print(p.c,p.l,p.r,p.d,p.p1,p.p2);
}
int main()
{
int n,m,k;
scanf("%d %d %d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
sum[i][j]=sum[i-1][j]+a[i][j];
}
}
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=m;j++) printf("%d ",sum[i][j]);
// putchar('\n');
// }
int ans=0;
for(int c=1;c<=m;c++) // column
{
for(int l=1;l<=n;l++)
{
for(int r=l;r<=n;r++)
{
for(int d=r-l+1;d<=k;d++)
{
// ----- 0, 0 -----
// 0, 0 -> 0, 0
for(int ll=l;ll<=r;ll++)
{
for(int rr=ll;rr<=r;rr++)
{
// dp[c][l][r][d][0][0]=max(dp[c][l][r][d][0][0],
// dp[c-1][ll][rr][d-(r-l+1)][0][0]+sum[r][c]-sum[l-1][c]);
if(dp[c-1][ll][rr][d-(r-l+1)][0][0]+sum[r][c]-sum[l-1][c]>dp[c][l][r][d][0][0])
{
dp[c][l][r][d][0][0]=dp[c-1][ll][rr][d-(r-l+1)][0][0]+sum[r][c]-sum[l-1][c];
pre[c][l][r][d][0][0]=Pre(c-1,ll,rr,d-(r-l+1),0,0);
}
}
}
// ----- 0, 1 -----
// 0, 1 -> 0, 1
for(int ll=l;ll<=r;ll++)
{
for(int rr=r;rr<=n;rr++)
{
// dp[c][l][r][d][0][1]=max(dp[c][l][r][d][0][1],
// dp[c-1][ll][rr][d-(r-l+1)][0][1]+sum[r][c]-sum[l-1][c]);
if(dp[c-1][ll][rr][d-(r-l+1)][0][1]+sum[r][c]-sum[l-1][c]>dp[c][l][r][d][0][1])
{
dp[c][l][r][d][0][1]=dp[c-1][ll][rr][d-(r-l+1)][0][1]+sum[r][c]-sum[l-1][c];
pre[c][l][r][d][0][1]=Pre(c-1,ll,rr,d-(r-l+1),0,1);
}
}
}
//0, 0 -> 0, 1
for(int ll=l;ll<=r;ll++)
{
for(int rr=ll;rr<=r;rr++)
{
// dp[c][l][r][d][0][1]=max(dp[c][l][r][d][0][1],
// dp[c-1][ll][rr][d-(r-l+1)][0][0]+sum[r][c]-sum[l-1][c]);
if(dp[c-1][ll][rr][d-(r-l+1)][0][0]+sum[r][c]-sum[l-1][c]>dp[c][l][r][d][0][1])
{
dp[c][l][r][d][0][1]=dp[c-1][ll][rr][d-(r-l+1)][0][0]+sum[r][c]-sum[l-1][c];
pre[c][l][r][d][0][1]=Pre(c-1,ll,rr,d-(r-l+1),0,0);
}
}
}
// ----- 1, 0 -----
// 1, 0 -> 1, 0
for(int ll=1;ll<=l;ll++)
{
for(int rr=l;rr<=r;rr++)
{
// dp[c][l][r][d][1][0]=max(dp[c][l][r][d][1][0],
// dp[c-1][ll][rr][d-(r-l+1)][1][0]+sum[r][c]-sum[l-1][c]);
if(dp[c-1][ll][rr][d-(r-l+1)][1][0]+sum[r][c]-sum[l-1][c]>dp[c][l][r][d][1][0])
{
dp[c][l][r][d][1][0]=dp[c-1][ll][rr][d-(r-l+1)][1][0]+sum[r][c]-sum[l-1][c];
pre[c][l][r][d][1][0]=Pre(c-1,ll,rr,d-(r-l+1),1,0);
}
}
}
// 0, 0 -> 1, 0
for(int ll=l;ll<=r;ll++)
{
for(int rr=ll;rr<=r;rr++)
{
// dp[c][l][r][d][1][0]=max(dp[c][l][r][d][1][0],
// dp[c-1][ll][rr][d-(r-l+1)][0][0]+sum[r][c]-sum[l-1][c]);
if(dp[c-1][ll][rr][d-(r-l+1)][0][0]+sum[r][c]-sum[l-1][c]>dp[c][l][r][d][1][0])
{
dp[c][l][r][d][1][0]=dp[c-1][ll][rr][d-(r-l+1)][0][0]+sum[r][c]-sum[l-1][c];
pre[c][l][r][d][1][0]=Pre(c-1,ll,rr,d-(r-l+1),0,0);
}
}
}
// ----- 1, 1 -----
// 1, 1 -> 1, 1
for(int ll=1;ll<=l;ll++)
{
for(int rr=r;rr<=n;rr++)
{
// dp[c][l][r][d][1][1]=max(dp[c][l][r][d][1][1],
// dp[c-1][ll][rr][d-(r-l+1)][1][1]+sum[r][c]-sum[l-1][c]);
if(dp[c-1][ll][rr][d-(r-l+1)][1][1]+sum[r][c]-sum[l-1][c]>dp[c][l][r][d][1][1])
{
dp[c][l][r][d][1][1]=dp[c-1][ll][rr][d-(r-l+1)][1][1]+sum[r][c]-sum[l-1][c];
pre[c][l][r][d][1][1]=Pre(c-1,ll,rr,d-(r-l+1),1,1);
}
}
}
// 1, 0 -> 1, 1
for(int ll=1;ll<=l;ll++)
{
for(int rr=l;rr<=r;rr++)
{
// dp[c][l][r][d][1][1]=max(dp[c][l][r][d][1][1],
// dp[c-1][ll][rr][d-(r-l+1)][1][0]+sum[r][c]-sum[l-1][c]);
if(dp[c-1][ll][rr][d-(r-l+1)][1][0]+sum[r][c]-sum[l-1][c]>dp[c][l][r][d][1][1])
{
dp[c][l][r][d][1][1]=dp[c-1][ll][rr][d-(r-l+1)][1][0]+sum[r][c]-sum[l-1][c];
pre[c][l][r][d][1][1]=Pre(c-1,ll,rr,d-(r-l+1),1,0);
}
}
}
// 0, 1 -> 1, 1
for(int ll=l;ll<=r;ll++)
{
for(int rr=r;rr<=n;rr++)
{
// dp[c][l][r][d][1][1]=max(dp[c][l][r][d][1][1],
// dp[c-1][ll][rr][d-(r-l+1)][0][1]+sum[r][c]-sum[l-1][c]);
if(dp[c-1][ll][rr][d-(r-l+1)][0][1]+sum[r][c]-sum[l-1][c]>dp[c][l][r][d][1][1])
{
dp[c][l][r][d][1][1]=dp[c-1][ll][rr][d-(r-l+1)][0][1]+sum[r][c]-sum[l-1][c];
pre[c][l][r][d][1][1]=Pre(c-1,ll,rr,d-(r-l+1),0,1);
}
}
}
// 0, 0 -> 1, 1
for(int ll=l;ll<=r;ll++)
{
for(int rr=ll;rr<=r;rr++)
{
// dp[c][l][r][d][1][1]=max(dp[c][l][r][d][1][1],
// dp[c-1][ll][rr][d-(r-l+1)][0][0]+sum[r][c]-sum[l-1][c]);
if(dp[c-1][ll][rr][d-(r-l+1)][0][0]+sum[r][c]-sum[l-1][c]>dp[c][l][r][d][1][1])
{
dp[c][l][r][d][1][1]=dp[c-1][ll][rr][d-(r-l+1)][0][0]+sum[r][c]-sum[l-1][c];
pre[c][l][r][d][1][1]=Pre(c-1,ll,rr,d-(r-l+1),0,0);
}
}
}
if(d==k)
{
// ans=max(ans,dp[c][l][r][d][0][0]);
// ans=max(ans,dp[c][l][r][d][0][1]);
// ans=max(ans,dp[c][l][r][d][1][0]);
// ans=max(ans,dp[c][l][r][d][1][1]);
if(dp[c][l][r][d][0][0]>ans)
{
ans=dp[c][l][r][d][0][0];
Ans=Pre(c,l,r,d,0,0);
}
if(dp[c][l][r][d][0][1]>ans)
{
ans=dp[c][l][r][d][0][1];
Ans=Pre(c,l,r,d,0,1);
}
if(dp[c][l][r][d][1][0]>ans)
{
ans=dp[c][l][r][d][1][0];
Ans=Pre(c,l,r,d,1,0);
}
if(dp[c][l][r][d][1][1]>ans)
{
ans=dp[c][l][r][d][1][1];
Ans=Pre(c,l,r,d,1,1);
}
}
}
}
}
}
printf("Oil : %d",ans);
Print(Ans.c,Ans.l,Ans.r,Ans.d,Ans.p1,Ans.p2);
return 0;
}