I区域
给定一个矩阵 求大小为k的凸多边形的权值最大值
轮廓线dp
思路很好想 但是细节很多
//错误点1: 为了保证必须有交集,q不应该从p+1开始枚举 而应该从l开始枚举
//错误点2: 左右边界相等的时候不是空集 而是大小为1的集合 枚举的时候要注意
//错误点3: 目标不一定是从第一行~第n行都占着了 所以在统计结果的时候要枚举 应当把g.j=0作为递归输出的边界
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=16;
int read()
{
int x=0,f=0,c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return f?-x:x;
}
int a[N][N];
int n,m,k,sum[N][N];
struct Node
{
int i,j,l,r,x,y;
}pp[N][N*N][N][N][2][2];
int f[N][N*N][N][N][2][2];
void print(Node g)
{
if(!g.i) return;
Node t=pp[g.i][g.j][g.l][g.r][g.x][g.y];
for(int i=g.l;i<=g.r;i++)
printf("%d %d\n",g.i,i);
print(t);
}
int main()
{
n=read(); m=read(); k=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
a[i][j]=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
sum[i][j]=sum[i][j-1]+a[i][j];
//row sum l_limit r_limit statel=_l state_r
//0: down 1: up
for(int i=1;i<=n;i++)
for(int j=1;j<=min(k,i*m);j++)
for(int l=1;l<=n;l++)
for(int r=l+1;r<=n;r++)
{
int t=r-l+1,s=sum[i][r]-sum[i][l-1];
if(j-t<=0){ f[i][j][l][r][0][1]=s; break;}
for(int p=l;p<=r;p++)
for(int q=p+1;q<=r;q++)
if(f[i][j][l][r][0][1]<f[i-1][j-t][p][q][1][0]+s)
{
f[i][j][l][r][0][1]=f[i-1][j-t][p][q][1][0]+s;
pp[i][j][l][r][0][1]=(Node){i-1,j-t,p,q,1,0};
}
for(int p=1;p<=l;p++)
for(int q=r;q<=n;q++)
for(int x=0;x<=1;x++)
for(int y=0;y<=1;y++)
if(f[i][j][l][r][1][0]<f[i-1][j-t][p][q][x][y]+s)
f[i][j][l][r][1][0]=f[i-1][j-t][p][q][x][y]+s,
pp[i][j][l][r][1][0]=(Node){i-1,j-t,p,q,x,y};
for(int p=l;p<=r;p++)
for(int q=r;q<=m;q++)
for(int x=0;x<=1;x++)
if(f[i][j][l][r][1][1]<f[i-1][j-t][p][q][x][1]+s)
f[i][j][l][r][1][1]=f[i-1][j-t][p][q][x][1]+s,
pp[i][j][l][r][1][1]=(Node){i-1,j-t,p,q,x,1};
for(int p=1;p<=l;p++)
for(int q=p+1;q<=r;q++)
for(int y=0;y<=1;y++)
if( f[i][j][l][r][0][0]<f[i-1][j-t][p][q][0][y]+s)
f[i][j][l][r][0][0]=f[i-1][j-t][p][q][0][y]+s,
pp[i][j][l][r][0][0]=(Node){i-1,j-t,p,q,0,y};
}
int ret=0;Node ans;
for(int l=1;l<=n;l++)
for(int r=l+1;r<=n;r++)
for(int x=0;x<=1;x++)
for(int y=0;y<=n;y++)
if(ret<f[n][k][l][r][x][y])
ret=f[n][k][l][r][x][y],
ans=(Node){n,k,l,r,x,y};
printf("Oil : %d\n",ret);
print(ans);
return 0;
}
调试代码的时候尽量利用最优子结构的性质

浙公网安备 33010602011771号