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;
}

调试代码的时候尽量利用最优子结构的性质

posted @ 2022-02-08 17:07  __iostream  阅读(60)  评论(0)    收藏  举报