着色

题目

 Alice是一个奇怪的画家。她想对一副有N*N个像素点组成的画进行着色,N是2的幂(1,2,4,8,16等等)。每个像素点可以着成黑色或白色。
  Alice着色方案不是唯一的,她采用以下不确定的规则:
  •如果画作只有一个像素点,那可以直接着白色或黑色;
  •否则,把画平均分成四块,然后进行以下操作:
  (1) 选择一块全部着白色;
  (2) 选择一块全部着黑色;
  (3) 把剩下的两块当作是独立的画作并采用同样的方法进行着色。
  对于每一幅画作,Alice心目中已经有一个蓝图,接下来请你帮她采用上述方法着色,要求选择跟心目中的蓝图差异最小的着色方案,当然要遵循上述的着色规则,两幅图的差异是指对应位置颜色不相同的像素点的个数。

分析

考虑dp,
定义(f_{i,j,k,l}(其中0<=k<=log_{2}n)),表示对于一个矩阵,左上角的点是((i,j)),大小为((2^{k})^{2}),矩阵类型(l)(0表示全为白色的不同原图的个数,1表示全为黑色的不同原图的个数,2表示这个矩阵的最优着色方案)。
显然,答案就是(f_{1,1,log_{2}n,2})
那么转移也显然

[f_{i,j,k,0}=f_{i,j,k-1,0}+f_{i+2^{k-1},j,k-1,0}+f_{i,j+2^{k-1},k-1,0}+f_{i+2^{k-1},j+2^{k-1},k-1,0} ]

[f_{i,j,k,1}=f_{i,j,k-1,1}+f_{i+2^{k-1},j,k-1,1}+f_{i,j+2^{k-1},k-1,1}+f_{i+2^{k-1},j+2^{k-1},k-1,1} ]

[f_{i,j,k,2}=f_{i,j,k-1,a}+f_{i+2^{k-1},j,k-1,b}+f_{i,j+2^{k-1},k-1,c}+f_{i+2^{k-1},j+2^{k-1},k-1,d} ]

其中(a、b、c、d)中,一个是0,一个是1,剩余的两个是2。

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const int maxlongint=2147483647;
const int mo=1000000007;
const int N=515;
using namespace std;
int a[N][N],n,m,f[N][N][11][3],mi[20],z[4][2]
={{1,0},{0,0},{0,1},{1,1}};
int i,j,k;
int solve(int p,int q,int p1,int q1)
{
	int t;
	p-=1;
	p1-=1;
	q1-=1;
	q-=1;
	t=f[i+mi[k-1]*z[p][0]][j+mi[k-1]*z[p][1]][k-1][0]+
	f[i+mi[k-1]*z[p1][0]][j+mi[k-1]*z[p1][1]][k-1][1]+
	f[i+mi[k-1]*z[q][0]][j+mi[k-1]*z[q][1]][k-1][2]+
	f[i+mi[k-1]*z[q1][0]][j+mi[k-1]*z[q1][1]][k-1][2];
	if(t<f[i][j][k][2]) f[i][j][k][2]=t;
}
int main()
{
	memset(f,43,sizeof(f));
	mi[0]=1;
	for(i=1;i<=15;i++)
		mi[i]=mi[i-1]*2;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
		for(j=1;j<=n;j++)
		{
			char c;
			c=getchar();
			while(c!='1' && c!='0')	
				c=getchar();
			a[i][j]=c-48;
			f[i][j][0][0]=a[i][j];
			f[i][j][0][1]=1-a[i][j];
			f[i][j][0][2]=0;
		}
	int lo=log2(n);
	for(k=1;k<=lo;k++)
	{
		for(i=1;i<=n-mi[k]+1;i++)
			for(j=1;j<=n-mi[k]+1;j++)
			{
				f[i][j][k][0]=f[i][j][k-1][0]+f[i+mi[k-1]][j][k-1][0]+f[i][j+mi[k-1]][k-1][0]+f[i+mi[k-1]][j+mi[k-1]][k-1][0];
				f[i][j][k][1]=f[i][j][k-1][1]+f[i+mi[k-1]][j][k-1][1]+f[i][j+mi[k-1]][k-1][1]+f[i+mi[k-1]][j+mi[k-1]][k-1][1];
				solve(1,2,3,4);
				solve(1,2,4,3);
				solve(1,3,2,4);
				solve(2,1,3,4);
				solve(2,1,4,3);
				solve(2,3,1,4);
				solve(3,1,2,4);
				solve(3,1,4,2);
				solve(3,4,1,2);
				solve(4,1,2,3);
				solve(4,1,3,2);
				solve(4,2,1,3);
			}
	}
	printf("%d",f[1][1][lo][2]);
}

原文地址:https://www.cnblogs.com/chen1352/p/9013505.html