1 条题解
-
0
自动搬运
来自洛谷,原作者为

ouuan
如果奇迹有颜色的话,那么其中之一必是橙色的吧。搬运于
2025-08-24 21:59:23,当前版本为作者最后更新于2018-04-06 17:58:41,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
作为一名非正式蒟蒻,凭着A掉这题在弱省HB拿了d1rank2,于是发篇题解祝贺自己人生首次尝试状压便AC
画图之后可以发现每行的棋子数是一个递增序列,即上一行的棋子数一定比下一行多,而且每一行的棋子都是从左往右那么多个,也就是说确定了每一行的棋子数就确定了整个局面,所以关键就是如何简洁地表示一个递增序列。
不要问我怎么想到的,我们可以先写m个0,然后看每一行,有几个棋子就在第几个0后面插入一个1
e.g.
xxxxo
xxooo
xoooo
xoooo
ooooo
就是1011010010
然后这玩意就是我们要的状态
那么转移方程呢?其实得出状态的表示方法之后方程就很好写了,实现起来略复杂,但想通了也不难
ab(u)表示状态u的局面有奇数颗棋子还是偶数颗棋子,即下一步该谁下,计算的方法是从最高位开始向下遍历,累计有奇数个0时遍历到1便把输出取反,实现如下:
bool ab(int u) { int i; bool odd=false,out=false; for (i=1<<(n+m-1);i>0;i>>=1) { if (i&u) { if (odd) { out=!out; } } else { odd=!odd; } } return out; }存a和b时a[i][j]=A[i][m+1-j]会稍微方便一些
然后就是最终的方程:f(i)=若ab(i)则为min,否则为max{f(把每个后面一位非1&&不是最后一位的1分别向后移一位)+ab(i)?(-b[逆数第几个1后移][移之前这个1后面有几个0]):a[逆数第几个1后移][移之前这个1后面有几个0]}
这个方程的文字看起来非常复杂,所以建议自行理解并写出方程,如果看不懂的话可以结合下面的代码:
for (i=mini+1;i<=maxi;++i) { flag=false; one=zero=0; if (ab(i)) { f[i]=0x7fffffff; for (j=1;j<(1<<(n+m));j<<=1) { if (j&i) { ++one; if (flag) { f[i]=min(f[i],f[i-(j>>1)]-b[one][zero]); } flag=false; } else { ++zero; flag=true; } } } else { f[i]=-0x7fffffff; for (j=1;j<(1<<(n+m));j<<=1) { if (j&i) { ++one; if (flag) { f[i]=max(f[i],f[i-(j>>1)]+a[one][zero]); } flag=false; } else { ++zero; flag=true; } } } }完整代码就不给出了,还是建议看懂状态的表示之后剩余部分全部自行写出
- 1
信息
- ID
- 3368
- 时间
- 1000ms
- 内存
- 500MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者