• 【CH5104】I-country 线性dp+路径输出


    pre:在网格中,凸多边形可以按行(row)分解成若干段连续的区间 [ l , r ] ,且左端点纵坐标的值(col)满足先减后增,右端点纵坐标先增后减。
    阶段:根据这个小发现,可以将阶段设置成每一行,因此,解决这个问题一共需要N个阶段。
    状态:除了阶段外,表示每一个状态还需要记录下当前阶段下一共选了多少个网格,当前行选择的区间 [ l , r ] ,和相对于上一行来说端点选择的单调性。(0表示单调递增,1表示单调递减)
    因此,状态可以表示成为(dp[i][j][l][r][x][y])
    状态转移方程:分成四种情况进行讨论,详见代码。

    第二个要实现的是路径输出,可以额外使用与状态大小相同的数组来记录下当前状态是从哪个状态转移而来的,最后从末状态经过一次递归即可得到路径。

    代码如下

    #include <bits/stdc++.h>
    #define forto(i,a,b) for(i=a;i<=b;i++)//循环宏定义,减小代码量
    using namespace std;
    
    int n,m,k,sum[20][20];
    int f[16][226][16][16][2][2];
    struct node{
    	int l,r,x,y;
    }pre[16][226][16][16][2][2];
    
    void read_and_parse(){
    	scanf("%d%d%d",&n,&m,&k);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++){
    			scanf("%d",&sum[i][j]);
    			sum[i][j]+=sum[i][j-1];
    		}
    }
    
    int x,y,i,j,l,r,ans,ai,al,ar,ax,ay;//本题状态数较多,因此采用当前变量全局化,避免参数传递混乱
    
    inline void update(int dat,int L,int R,int X,int Y){
    	int& ans=f[i][j][l][r][x][y];//使用引用减小代码量
    	node& p=pre[i][j][l][r][x][y];
    	if(ans>=dat)return;
    	ans=dat;
    	p=(node){L,R,X,Y};
    }
    
    void print(int i,int j,int l,int r,int x,int y){
    	if(!j)return;
    	node& p=pre[i][j][l][r][x][y];
    	print(i-1,j-(r-l+1),p.l,p.r,p.x,p.y);
    	forto(j,l,r)printf("%d %d
    ",i,j);
    }
    
    void solve(){
    	forto(i,1,n)forto(j,1,k)forto(l,1,m)forto(r,l,m){
    		int t=r-l+1;if(t>j)break;
    		int now=sum[i][r]-sum[i][l-1];
    		x=y=1;
    		for(int p=l;p<=r;p++)
    			for(int q=r;q<=m;q++){
    				update(f[i-1][j-t][p][q][1][0]+now,p,q,1,0);
    				update(f[i-1][j-t][p][q][1][1]+now,p,q,1,1);
    			}
    		x=1,y=0;
    		for(int p=l;p<=r;p++)
    			for(int q=p;q<=r;q++)
    				update(f[i-1][j-t][p][q][1][0]+now,p,q,1,0);
    		x=0,y=1;
    		for(int p=1;p<=l;p++)
    			for(int q=r;q<=m;q++){
    				update(f[i-1][j-t][p][q][1][1]+now,p,q,1,1);
    				update(f[i-1][j-t][p][q][1][0]+now,p,q,1,0);
    				update(f[i-1][j-t][p][q][0][1]+now,p,q,0,1);
    				update(f[i-1][j-t][p][q][0][0]+now,p,q,0,0);
    			}
    		x=y=0;
    		for(int p=1;p<=l;p++)
    			for(int q=l;q<=r;q++){
    				update(f[i-1][j-t][p][q][1][0]+now,p,q,1,0);
    				update(f[i-1][j-t][p][q][0][0]+now,p,q,0,0);
    			}
    	}
    	forto(i,1,n)forto(l,1,m)forto(r,l,m)forto(x,0,1)forto(y,0,1)
    		if(ans<f[i][k][l][r][x][y]){
    			ans=f[i][k][l][r][x][y];
    			ai=i,al=l,ar=r,ax=x,ay=y;
    		}
    	printf("Oil : %d
    ",ans);
    	print(ai,k,al,ar,ax,ay);//传入终点状态参数
    }
    
    int main(){
    	read_and_parse();
    	solve();
    	return 0;
    }
    
  • 相关阅读:
    异步加载text资源,加载一次、执行一次、链式回调
    贝叶斯判断类别
    通过贝叶斯概率机器学习
    什么是 Dropout
    什么是CNN--Convolutional Neural Networks
    神经网络介绍
    神经网络之线性单元
    机器学习十大常用算法
    对比学习用 Keras 搭建 CNN RNN 等常用神经网络
    机器学习,人工智能相关最新图书推荐
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/9790976.html
Copyright © 2020-2023  润新知