1 条题解

  • 0
    @ 2025-10-8 16:56:26
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=17,inf=0x3f3f3f3f;
    int a[N][N],s[N][N],f[N][N*N][N][N][2][2];
    //第一维:当前行数
    //第二维:已选格数
    //第三维:左端点坐标
    //第四维:右端点坐标
    //第五维:左端点递增/递减
    //第六维:右端点递增/递减
    struct path{int i,j,l,r,x,y;}p[N][N*N][N][N][2][2];
    //上一步所对应的信息
    int getsum(int k,int l,int r){return s[k][r]-s[k][l-1];}//前缀和
    void getpath(path t){//反推转移路径
    	if(!t.i||!t.j)return;
    	getpath(p[t.i][t.j][t.l][t.r][t.x][t.y]);
    	for(int k=t.l;k<=t.r;++k)
    		printf("%d %d\n",t.i,k);
    }
    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]),s[i][j]=s[i][j-1]+a[i][j];
    	memset(f,0xcf,sizeof(f));//将f数组置为-inf
    	for(int i=1;i<=n;++i)
    		for(int j=0;j<=k;++j)
    			for(int l=1;l<=m;++l)
    				for(int r=l;r<=m&&r-l+1<=j;++r){
    					{//左右端点均扩张
    						int &v=f[i][j][l][r][1][0];
    						path &t=p[i][j][l][r][1][0];
    						if(r-l+1==j)v=0;
    						else for(int p=l;p<=r;++p)
    							for(int q=p;q<=r&&q-p+1<=j-(r-l+1);++q){
    								int tv=f[i-1][j-(r-l+1)][p][q][1][0];
    								if(v<tv)
    									v=tv,t={i-1,j-(r-l+1),p,q,1,0};
    							}
    						v+=getsum(i,l,r);
    					}
    					{//左端点扩张,右端点缩减
    						int &v=f[i][j][l][r][1][1];
    						path &t=p[i][j][l][r][1][1];
    						for(int p=l;p<=r;++p)
    							for(int q=r;q<=m&&q-p+1<=j-(r-l+1);++q)
    								for(int y=0;y<=1;++y){
    									int tv=f[i-1][j-(r-l+1)][p][q][1][y];
    									if(v<tv)
    										v=tv,t={i-1,j-(r-l+1),p,q,1,y};
    								}
    						v+=getsum(i,l,r);
    					}
    					{//左端点缩减,右端点扩张
    						int &v=f[i][j][l][r][0][0];
    						path &t=p[i][j][l][r][0][0];
    						for(int p=1;p<=l;++p)
    							for(int q=l;q<=r&&q-p+1<=j-(r-l+1);++q)
    								for(int x=0;x<=1;++x){
    									int tv=f[i-1][j-(r-l+1)][p][q][x][0];
    									if(v<tv)
    										v=tv,t={i-1,j-(r-l+1),p,q,x,0};
    								}
    						v+=getsum(i,l,r);
    					}
    					{//左右端点均缩减
    						int &v=f[i][j][l][r][0][1];
    						path &t=p[i][j][l][r][0][1];
    						for(int p=1;p<=l;++p)
    							for(int q=r;q<=m&&q-p+1<=j-(r-l+1);++q)
    								for(int x=0;x<=1;++x)
    									for(int y=0;y<=1;++y){
    										int tv=f[i-1][j-(r-l+1)][p][q][x][y];
    										if(v<tv)
    											v=tv,t={i-1,j-(r-l+1),p,q,x,y};
    									}
    						v+=getsum(i,l,r);
    					}
    				}
    	int ans=0;path last={0,0,0,0,0,0};
    	for(int i=1;i<=n;++i)
    		for(int l=1;l<=m;++l)
    			for(int r=1;r<=m;++r)
    				for(int x=0;x<=1;++x)
    					for(int y=0;y<=1;++y){
    						int t=f[i][k][l][r][x][y];
    						if(ans<t)
    							ans=t,last={i,k,l,r,x,y};
    					}
    	printf("Oil : %d\n",ans);
    	getpath(last);
    	return 0;
    }

    • 1

    0x50 动态规划(0x51 线性DP)例题6:I-区域(spj)

    信息

    ID
    1363
    时间
    1000ms
    内存
    256MiB
    难度
    5
    标签
    递交数
    54
    已通过
    23
    上传者