题目

P3160 [CQOI2012]局部极小值

一眼就是状压,接下来就不知道了\(qwq\)

做法

我们能手玩出局部小值最多差不多是\(8,9\)个的样子,\(dp_{i,j}\)为填满\(1~i\)数字,局部小值的状态为\(j\)

第\(k\)个局部极小值填\(i\):\(dp[i][j]=(dp[i][j]+dp[i-1][j^(1<<k-1)])%p\)

不填在局部极小值,显然有些地方不能填\(i\)的,首先还没填的局部极小值不填,其周围也不能填(填\(i\)后后面再填比不符合局部极小值)

我们预处理出每种状态不能填时的位置:\(dp[i][j]=(dp[i][j]+dp[i-1][j]*max(num[j]-i+1,0))%p\)

一顿操作后发现WA了,我们得到的局部极小值可能不是恰好是给出的\(X\)(更多)

容斥原理:Ans=至少多0个极小值-至少多1个极小值+至少多两个极小值......

理解:至少多0个\((x,x+1,x+2,x+3...)-k(x+1,x+2,x+3...)\)其中\(k\)为某些值的系数

填了至少多0个极小值后,有多填的部分那就得减去至少多1个极小值,至少多1个极小值的位置也有很多,就会有一些位置减掉的系数为(k>1),就要又加上

\(dfs\)时加上能被多余的极小值填上的地方换成'X',然后多次做\(dp\)

My complete code

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<algorithm>
  4. #include<cstring>
  5. using namespace std;
  6. typedef long long LL;
  7. const int maxn=31;
  8. const int p=12345678;
  9. const int dx[8]={-1,-1,-1,0,1,1,1,0},dy[8]={-1,0,1,1,1,0,-1,-1};
  10. int n,m,tot;
  11. LL ans;
  12. int x[maxn],y[maxn],num[1<<9],dp[maxn][1<<9];
  13. bool visit[maxn][maxn];
  14. char s[maxn][maxn];
  15. inline int Solve(){
  16. tot=0;
  17. for(int i=1;i<=n;++i)
  18. for(int j=1;j<=m;++j)
  19. if (s[i][j]=='X')
  20. x[++tot]=i,
  21. y[tot]=j;
  22. int Up=1<<tot;
  23. for(int i=0;i<Up;i++){
  24. int cnt(0);
  25. memset(visit,0,sizeof(visit));
  26. for(int j=1;j<=tot;++j)
  27. if(!((i>>(j-1))&1)){
  28. visit[x[j]][y[j]]=1;
  29. for(int k=0;k<8;++k){
  30. int xx=x[j]+dx[k];
  31. int yy=y[j]+dy[k];
  32. if(xx>0&&yy>0&&xx<=n&&yy<=m)
  33. visit[xx][yy]=1;
  34. }
  35. }
  36. for(int j=1;j<=n;++j)
  37. for(int k=1;k<=m;++k)
  38. if(visit[j][k])
  39. ++cnt;
  40. num[i]=n*m-cnt;
  41. }
  42. memset(dp,0,sizeof(dp));
  43. dp[0][0]=1;
  44. for(int i=1;i<=n*m;++i)
  45. for(int j=0;j<Up;++j){
  46. dp[i][j]=(dp[i][j]+dp[i-1][j]*max(num[j]-i+1,0))%p;
  47. for(int k=1;k<=tot;k++)
  48. if(j&(1<<(k-1)))
  49. dp[i][j]=(dp[i][j]+dp[i-1][j^(1<<k-1)])%p;
  50. }
  51. return dp[n*m][Up-1];
  52. }
  53. void Dfs(int x,int y,int k){
  54. if(y==m+1){
  55. Dfs(x+1,1,k);
  56. return;
  57. }
  58. if(x==n+1){
  59. ans=(ans+(((k&1)==0)?1:-1)*Solve()+p)%p;
  60. return;
  61. }
  62. Dfs(x,y+1,k);
  63. if(s[x][y]!='X'){
  64. bool f=true;
  65. for(int i=0;i<8;i++)
  66. if(s[x+dx[i]][y+dy[i]]=='X'){
  67. f=false;
  68. break;
  69. }
  70. if(f){
  71. s[x][y]='X',
  72. Dfs(x,y+1,k+1),
  73. s[x][y]='.';
  74. }
  75. }
  76. }
  77. int main(){
  78. scanf("%d%d",&n,&m);
  79. for(int i=1;i<=n;i++)
  80. scanf(" %s",s[i]+1);
  81. Dfs(1,1,0);
  82. printf("%lld\n",ans);
  83. return 0;
  84. }
  85. /*
  86. 5 5
  87. .....
  88. ...X.
  89. .X...
  90. .....
  91. ....X
  92. */

P3160 [CQOI2012]局部极小值的更多相关文章

  1. P3160 [CQOI2012]局部极小值 题解(状压DP+容斥)

    题目链接 P3160 [CQOI2012]局部极小值 双倍经验,双倍快乐 解题思路 存下来每个坑(极小值点)的位置,以这个序号进行状态压缩. 显然,\(4*7\)的数据范围让极小值点在8个以内(以下示 ...

  2. BZOJ 2669 Luogu P3160 [CQOI2012]局部极小值 (容斥原理、DP)

    题目链接 (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=2669 (luogu) https://www.luogu.org/prob ...

  3. bzoj 2669 [cqoi2012]局部极小值 DP+容斥

    2669: [cqoi2012]局部极小值 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 838  Solved: 444[Submit][Status ...

  4. bzoj2669[cqoi2012]局部极小值 容斥+状压dp

    2669: [cqoi2012]局部极小值 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 774  Solved: 411[Submit][Status ...

  5. [BZOJ2669] [cqoi2012]局部极小值

    [BZOJ2669] [cqoi2012]局部极小值 Description 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所有相邻格子(相邻是指有公共边或公共顶点) ...

  6. 【BZOJ 2669】 2669: [cqoi2012]局部极小值 (状压DP+容斥原理)

    2669: [cqoi2012]局部极小值 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 667  Solved: 350 Description 有一 ...

  7. BZOJ2669 [cqoi2012]局部极小值 状压DP 容斥原理

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2669 题意概括 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所 ...

  8. 【bzoj2669】[cqoi2012]局部极小值 容斥原理+状压dp

    题目描述 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所有相邻格子(相邻是指有公共边或公共顶点)都小,我们说这个格子是局部极小值. 给出所有局部极小值的位置,你的任 ...

  9. BZOJ 2669 CQOI2012 局部极小值 状压dp+容斥原理

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2669 题意概述:实际上原题意很简洁了我就不写了吧.... 二话不说先观察一下性质,首先棋盘 ...

随机推荐

  1. Https所涉及名词及相关后缀名解释

    HTTPS: HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版.即 ...

  2. Android基础之使用Fragment控制切换多个页面

    Android官方已经提供了Fragment的各种使用的Demo例子,在我们SDK下面的API Demo里面就包含了Fragment的各种使用例子,需要看Demo的朋友,直接看API Demo那个程序 ...

  3. stage3D基础四----Stage3D和透视投影的使用(转)

    原文地址: http://www.adobe.com/cn/devnet/flashplayer/articles/perspective-projection.html 引言 在本教程中,你将了解透 ...

  4. Junit 内部解密之二: TestResult + TestListener + Assert

    转自:http://blog.sina.com.cn/s/blog_6cf812be0100wbhw.html 之前我们看到了Test接口里面的run方法有个TestResult的参数,不错,这个类就 ...

  5. 【Python+selenium】之奇怪问题总结

    问题1: <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'> Time Elapsed: 0:00:04 ...

  6. Spring读书笔记-----Spring核心机制:依赖注入

    spring框架为我们提供了三种注入方式,分别是set注入,构造方法注入,接口注入.今天就和大家一起来学习一下 依赖注入的基本概念 依赖注入(Dependecy Injection),也称为IoC(I ...

  7. java后端技术

    技术概论:Springmvc+mybatis+shiro+Dubbo+ZooKeeper+Redis+KafKa j2ee分布式架构 我在恒生工作,主要开发金融互联网第三方平台的对接项目.目前已经对接 ...

  8. js 抢月饼

    面源码: <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" co ...

  9. python在windows下安装paramiko模块和安装pycrypto模块(3步搞定)(转)

    Python中使用SSH需要用到OpenSSH,而OpenSSH依赖于paramiko模块,而paramiko模块又依赖于pycrypto模块,因此要在Python中使用SSH,我们需要先安装pycr ...

  10. intellij idea pycharm phpstorm webstorm 这些编辑器像 sublime text 一样使用 ctrl d 来操作光标多选。

    在Windows 和 Linux 快捷键是 Alt+J,在 Mac OS X 系统下快捷键是 Ctrl+G . 参考 https://blog.jetbrains.com/phpstorm/2014/ ...