[关闭]
@ruanxingzhi 2016-12-20T14:12:09.000000Z 字数 1280 阅读 1416

polya定理

这是组合数学中著名的定理。用于解决“本质不同的染色方案”计数问题。

问题

现在需要给的棋盘黑白染色。求本质不同的染色方案数。

如果某染色方案经过顺时针旋转后与别的染色方案相同,则称它们本质相同。

暴力

我们先暴力列出每种染色方案:
每种方案

发现本质不同的染色方案数有种:C1,C2,C6,C10,C12,C16

bunside引理

bunside引理是polya定理的基础。

为了讨论方便,先给格子编号。
编号

首先考虑“旋转”的本质——置换。旋转给出了一些置换方式,例如顺时针旋转,用置换的语言说就是“原来的位置是1的现在摆在2,原来位置是2的现在摆在3……”,表示为。类似地,我们搞出所有的置换:




接下来就是bunside引理了:

对于每个置换,我们定义在置换 下保持不变的方案数
则有: 本质不同的方案数为平均数
即:

用上面的例子来验证一下:

置换 保持不变的方案
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 16
1,16 2
1,10,11,16 4
1,16 2

的平均数为:,发现确实是答案。

polya定理

上面的bunside引理很好用,然而它需要枚举每个方案,复杂度十分不好。

所以polya定理出来拯救世界了。它提供了一种快速计算的方法:

考虑置换,我们一定能把它表示成循环的形式。例如上面的转可以表示为:

表示置换的循环节个数,表示有多少种颜色。则有:

我们还是使用之前的例子来验证。

角度 置换

从上面的例子中我们发现,确实等于。现在我们的任务只是求出了。它显然可以求出:

  1. int flag[10]={0},i,j,m=0;
  2. for(i=1;i<=4;i++)
  3. if(flag[i]==0)
  4. {
  5. j=i;
  6. while(flag[j]==0)
  7. flag[j]=1,j=f[j];
  8. m++;
  9. }

所以现在我们可以以的时间复杂度来求出整个问题的解。其中表示置换数量。

是不是很简单?

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注