LG4158 「SCOI2009」粉刷匠 线性DP

问题描述

LG4158


题解

(opt[i][j][k])代表到((i,k))刷了(j)次的方案数。

一开始DP顺序有点问题,调了很长时间。

务必考虑清楚DP顺序问题


(mathrm{Code})

#include<bits/stdc++.h>
using namespace std;

template <typename Tp>
void read(Tp &x){
	x=0;char ch=1;int fh;
	while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
	if(ch=='-'){
		fh=-1;ch=getchar();
	}
	else fh=1;
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+ch-'0';
		ch=getchar();
	}
	x*=fh;
}

const int maxn=53;

int n,m,t;
int a[maxn][maxn],s[maxn][maxn*maxn],opt[maxn][maxn*maxn][maxn];
int f[maxn][maxn*maxn];


void println_opt(){
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			for(int k=0;k<=t;k++){
				printf("opt[%d][%d][%d]=%d
",i,j,k,opt[i][j][k]);
			}
		}
	}
}

int main(){
	read(n);read(m);read(t);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			scanf("%1d",&a[i][j]);
			s[i][j]=s[i][j-1]+a[i][j];
		}
	}
//	opt[1][0][0]=1;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
//			int ed=min((i-1)*n+j,t);
			for(int k=1;k<=m;k++){
//				opt[i][j][k]=opt[i][0][k-1]+max(s[i][k],k-s[i][k]);
				for(int p=j-1;p<k;p++){
					opt[i][j][k]=max(opt[i][j][k],opt[i][j-1][p]+max(s[i][k]-s[i][p],k-p-(s[i][k]-s[i][p])));
				}
			}
		}
		//for(int j=1;j<=t;j++) opt[i+1][0][j]=opt[i][m][j];
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=t;j++){
			for(int k=0;k<=min(j,m);k++){
				f[i][j]=max(f[i][j],f[i-1][j-k]+opt[i][k][m]);
			}
		}
	}
	int ans=0;
	for(int i=1;i<=t;i++) ans=max(ans,f[n][i]);
	printf("%d
",ans);
//	println_opt();
	return 0;
}
原文地址:https://www.cnblogs.com/liubainian/p/11617714.html