【BZOJ1806】【IOI2007】Miners 矿工配餐 动态规划

#include <stdio.h>
int main()
{
	puts("转载请注明出处谢谢");
	puts("http://blog.csdn.net/vmurder/article/details/42969559");
}

题解:f[i][j][k][l][m]表示到第i个字母,第一坑的当前两个字母是jk,第二坑lm时的最大权值。

然后暴力瞎转移就好了。

对了,10W*4*4*4*4=2560W,64M内存限制,要写滚动数组。


代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 101000
#define inf 0x3f3f3f3f
using namespace std;
char s[N];
int f[2][4][4][4][4],n;
int now,last;
int main()
{
	freopen("test.in","r",stdin);
	int i,j,k,l,m;
	int a,b,alp;
	scanf("%d",&n);
	scanf("%s",s+1);
	now=1,last=0;
	memset(f[now],0xef,sizeof f[now]);
	f[now][0][0][0][0]=0;
	for(i=1;i<=n;i++)
	{
		if(s[i]=='M')alp=1;
		if(s[i]=='F')alp=2;
		if(s[i]=='B')alp=3;

		now^=1,last^=1;
		memset(f[now],0xef,sizeof f[now]);
		for(j=0;j<4;j++)
		{
			for(k=0;k<4;k++)
			{
				a=1;
				if(j)a++;
				if(k)a++;
				if(j==k&&j)a--;
				if(alp==j)a--;
				if(alp==k&&j!=k)a--;
				
				for(l=0;l<4;l++)
				{
					for(m=0;m<4;m++)
					{						
						b=1;
						if(l)b++;
						if(m)b++;
						if(l==m&&l)b--;
						if(alp==l)b--;
						if(alp==m&&l!=m)b--;

						//分配给矿坑1
						f[now][k][alp][l][m]=max(f[now][k][alp][l][m],f[last][j][k][l][m]+a);
						//分配给矿坑2
						f[now][j][k][m][alp]=max(f[now][j][k][m][alp],f[last][j][k][l][m]+b);
					}
				}
			}
		}
	}
	int ans=0;
	for(i=0;i<4;i++)for(j=0;j<4;j++)for(k=0;k<4;k++)for(l=0;l<4;l++)ans=max(ans,f[now][i][j][k][l]);
	printf("%d\n",ans);
}


你可能感兴趣的:(动态规划,IOI2007,BZOJ1806,Miners,矿工配餐)