1. 程式人生 > >bzoj1296 [SCOI2009]粉刷匠 區間dp+揹包

bzoj1296 [SCOI2009]粉刷匠 區間dp+揹包

每一條都是獨立的,所以可以分開處理

對於一條,粉刷一定是粉刷完完整的一條是最優的(不會有比它優的),所以列舉次數起點轉移

不同條之間就是分組揹包的關係了。。

碼:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int ff[5555],fff[5555],g[5555],tu[55][55],qsum1[55],qsum0[55],f[55][55],n,m,t,i,j,k,l;
int main()
{
	scanf("%d%d%d",&n,&m,&t);
for(i=1;i<=t;i++)ff[i]=-999999999;
	for(i=1;i<=n;i++)
	{
	for(j=1;j<=m;j++){scanf("%c",&tu[i][j]);while(tu[i][j]!='0'&&tu[i][j]!='1')scanf("%c",&tu[i][j]);	}
	}
	for(i=1;i<=n;i++)
	{	
	for(j=1;j<=m;j++)
	fff[j]=-999999999;
		memset(qsum1,0,sizeof(qsum1));
		memset(qsum0,0,sizeof(qsum0));
		memset(g,0,sizeof(g));
		memset(f,0,sizeof(f));
		for(j=1;j<=m;j++)
		{
		qsum1[j]=qsum1[j-1]+ (tu[i][j]=='0'?0:1);	
		qsum0[j]=qsum0[j-1]+ (tu[i][j]=='1'?0:1);			
		}	
		for(j=1;j<=m;j++)
		for(k=0;k<j;k++)
		for(l=1;l<=m;l++)
		{
			f[j][l]=max(f[k][l-1]+max(qsum1[j]-qsum1[k],qsum0[j]-qsum0[k]),f[j][l]);
		}
		for(j=1;j<=m;j++)
		{
		for(k=1;k<=m;k++)
		{
		g[j]=max(g[j],f[k][j]);	
		}	
		}
		for(j=1;j<=t;j++)
		{
			for(k=1;k<=m;k++)
			{
				if(j-k>=0)fff[j]=max(ff[j-k]+g[k],fff[j]);
			}
		}
		for(j=1;j<=t;j++)ff[j]=max(ff[j],fff[j]);
	}
	printf("%d",ff[t]);	
}