歌名 - 歌手
0:00

    着色

    题目

     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]);
    }
    
    
    posted @ 2018-05-09 12:33  无尽的蓝黄  阅读(196)  评论(0编辑  收藏  举报