摘要

题目链接 难度等级 完成状态 完成分数 最后编辑时间 失误原因(初次提交分数)
四子连棋 ★☆☆☆☆ 答案正确 100 2014/12/04 19:42:46 看漏条件(45)

题意

在4*4的棋盘,黑白双方交替走棋,任意一方可以先走,求到四子连棋的最小步数。

题解

  • 很明显就数据量来说,肯定是搜索题,一般来说求最小路径肯定是广搜。
  • 出于偷懒,写了迭代加深搜索。和广搜类似,由于前面若干层的搜索数据量十分小,可以通过限制并且不断加大搜索深度,以此来实现类似广度优先搜索的层次遍历。
  • 关于遍历:用一个delta数组来处理变化,详见5、96行。
  • 判重:其实不判重也能过了(已测试,注释掉86-89行),这里判重用了3进制压位(详见getID函数)。
  • 关于爆内存:好像ACM是无所谓内存的,一般来说128MB内存大概是3kw的int,6kw的short,12kw的bool,OIers特别注意下。

代码

1004.cpp代码已折叠
展开折叠内容
显示/移除行号
  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. using namespace std;
  5. const int deltaX[4]={0,0,1,-1},deltaY[4]={1,-1,0,0};
  6. char oC[2]={'B','W'};
  7. class state
  8. {
  9. private:
  10. char a[5][5];
  11. public:
  12. const bool isEnd() const
  13. {
  14. for(int i=1;i<=4;++i)
  15. {
  16. int xEnd=1,yEnd=1;
  17. for(int j=2;j<=4;++j)
  18. {
  19. if(a[j][i]!=a[j-1][i]||a[j][i]=='O')
  20. xEnd=0;
  21. if(a[i][j]!=a[i][j-1]||a[i][j]=='O')
  22. yEnd=0;
  23. }
  24. if(xEnd||yEnd)
  25. return 1;
  26. }
  27. int d1End=1,d2End=1;
  28. for(int i=2;i<=4;++i)
  29. {
  30. if(a[i][i]!=a[i-1][i-1]||a[i][i]=='O')
  31. d1End=0;
  32. if(a[i][5-i]!=a[i-1][5-i+1]||a[i][5-i]=='O')
  33. d2End=0;
  34. }
  35. if(d1End||d2End)
  36. return 1;
  37. return 0;
  38. }
  39. void init()
  40. {
  41. for(int i=1;i<=4;++i)
  42. {
  43. for(int j=1;j<=4;++j)
  44. cin>>a[i][j];
  45. }
  46. }
  47. void p()
  48. {
  49. for(int i=1;i<=4;++i)
  50. {
  51. for(int j=1;j<=4;++j)
  52. cout<<a[i][j];
  53. cout<<endl;
  54. }
  55. }
  56. inline const int getId() const
  57. {
  58. int p=0,u=1;
  59. for(int i=1;i<=4;++i)
  60. for(int j=1;j<=4;++j)
  61. {
  62. if(a[i][j]=='B')
  63. p+=1*u;
  64. if(a[i][j]=='W')
  65. p+=2*u;
  66. u*=3;
  67. }
  68. return p;
  69. }
  70. inline char *at(const int& x,const int& y)
  71. {
  72. if(x<1||x>4||y<1||y>4)
  73. return NULL;
  74. return &a[x][y];
  75. }
  76. };
  77. int stepL;
  78. short stepD[50000000]={};
  79. const bool dfs(state now,const int &step,bool color)
  80. {
  81. //now.p();
  82. if(step>stepL)
  83. return 0;
  84. if(now.isEnd())
  85. return 1;
  86. int nid=now.getId();
  87. if(stepD[nid]&&stepD[nid]<step)
  88. return 0;
  89. stepD[nid]=step;
  90. for(int i=1;i<=4;++i)
  91. {
  92. for(int j=1;j<=4;++j)
  93. {
  94. for(int dir=0;dir<4;++dir)
  95. {
  96. int newi=i+deltaX[dir],newj=j+deltaY[dir];
  97. if(now.at(newi,newj)==NULL)
  98. continue;
  99. if(*now.at(newi,newj)!='O'||*now.at(i,j)!=oC[color])//第一次写的时候没有看到要交替下棋
  100. continue;
  101. swap(*now.at(newi,newj),*now.at(i,j));
  102. if(dfs(now,step+1,!color))
  103. return 1;
  104. swap(*now.at(newi,newj),*now.at(i,j));
  105. }
  106. }
  107. }
  108. return 0;
  109. }
  110. state c;
  111. int main()
  112. {
  113. c.init();
  114. for(stepL=1;stepL<=100;++stepL)
  115. {
  116. if(dfs(c,1,0)||dfs(c,1,1)){
  117. printf("%d",stepL-1);
  118. return 0;
  119. }
  120. }
  121. }

著作权声明[编辑]

关于[编辑]