description
Alice是一个奇怪的画家。她想对一副有N*N个像素点组成的画进行着色,N是2的幂(1,2,4,8,16等等)。每个像素点可以着成黑色或白色。
Alice着色方案不是唯一的,她采用以下不确定的规则:
•如果画作只有一个像素点,那可以直接着白色或黑色;
•否则,把画平均分成四块,然后进行以下操作:
(1) 选择一块全部着白色;
(2) 选择一块全部着黑色;
(3) 把剩下的两块当作是独立的画作并采用同样的方法进行着色。
对于每一幅画作,Alice心目中已经有一个蓝图,接下来请你帮她采用上述方法着色,要求选择跟心目中的蓝图差异最小的着色方案,当然要遵循上述的着色规则,两幅图的差异是指对应位置颜色不相同的像素点的个数。
analysis
-
树形DPDPDP
考场dfs没调对 -
把大正方形看成一个树点,四个小正方形看成四个儿子节点
-
设f[i]f[i]f[i]表示当前矩阵的最小代价,先遍历整棵树
-
叶子结点肯定是000,向上回溯,记录每个矩阵中白点或黑点的个数
-
如果该儿子染白,代价就是黑点的个数;该儿子染黑,代价就是白点的个数
-
一种情况即为两个小矩阵染黑染白的代价加上剩下两个矩阵各自的fff
-
每个非叶节点共有十二种情况,枚举一遍,取最小值
code
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 515
#define ll long long
#define fo(i,a,b) for (ll i=a;i<=b;++i)
#define fd(i,a,b) for (ll i=a;i>=b;--i)
using namespace std;
ll a[MAXN][MAXN];
ll f[MAXN*MAXN*4],g[MAXN*MAXN*4];
ll n;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline void dfs(ll t,ll x,ll y,ll z)
{
if (z==1)
{
f[t]=0,g[t]=a[x][y];
return;
}
dfs(t*4-2,x,y,z/2),dfs(t*4-1,x,y+z/2,z/2),
dfs(t*4,x+z/2,y,z/2),dfs(t*4+1,x+z/2,y+z/2,z/2);
g[t]=g[t*4-2]+g[t*4-1]+g[t*4]+g[t*4+1];
fo(i,-2,1)fo(j,-2,1)if (i!=j)
{
ll tmp=z*z/4-g[t*4+i]/*white*/+g[t*4+j];/*black*/
fo(k,-2,1)if (k!=i && k!=j)tmp+=f[t*4+k];
f[t]=min(f[t],tmp);
}
}
int main()
{
//freopen("T3.in","r",stdin);
n=read(),scanf("\n");
fo(i,1,n)
{
fo(j,1,n)a[i][j]=getchar()-'0';
scanf("\n");
}
memset(f,127,sizeof(f)),dfs(1,1,1,n);
printf("%lld\n",f[1]);
return 0;
}

4179

被折叠的 条评论
为什么被折叠?



