怪盗基德之最后の战 vijos1614

vijos1614

 

我们来考虑这样一个方阵:

在左下角放上1,然后每个格子的左边即为这个格子中数的4倍,上面为5倍,则整个方阵就成为:

【下面是4*4的例子】

125

500

2000

8000

25

100

400

1600

5

20

80

320

1

4

16

64

于是我们就发现,剩下的牌都被完美地填进了这个方阵之中!

而实验证明,当k=12时,方阵已全部包含2^22内数字。因此方阵最大只需12*12

接下去我们要解决的就是在一个方阵中取若干个格子,任意两个格子都没有公共边。

显而易见,第i行怎么种,对前i-1行是没有影响的,因而符合无后效性原则。当然啦,这道题是没有所谓的最优解的。因此我们想到了什么?那就是递推~~

状态非常好写:f[i,j]表示第i行是j状态。j是二进制数,即一串01串,第i位是1表示这个格子取。那么f[i,j]=sigma(f[i-1,k])其中jk能够并存。

那么怎么判断jk能够并存呢?jk能够并存说明它们没有同一位上是1,j and k=0

当然还要判断j状态是否可行。比如说n=300,则第二行的状态1010是不可取的状态。也就是说,某列可以用能否取化为一个串0000…011…1,设它为g[i]g[i]01串中0为能取,1为不能取】。则必须满足g[i] and j=0。可以预处理a[i,j]表示第ij状态是否可行。最后只需把第n行能取的状态的总数全加起来即可。

【注意】还要判断,某行是否有两个连起来的格子被取,这个可以这样判断:

对状态j,只要j shr 1 and j=0即可

由于相邻的两个格子不能同时取,每行的状态被限制在了521个。同时还有不少格子本来就不能取,使得状态数进一步地减少了,因而最终时间复杂度最差也是O512^2*12)完全可以承受了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值