记录编号 417502 评测结果 AAA
题目名称 [UVa 11443] 网格里的树 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 1.056 s
提交时间 2017-06-25 20:16:26 内存使用 9.55 MiB
显示代码纯文本
  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. #include<queue>
  5. #include<map>
  6. using namespace std;
  7. int T,n,m,mod;
  8. char s[410][20];
  9. int inc(int x,int y){x+=y;return x>=mod?x-mod:x;}
  10. struct state{
  11. int fa[8],size[8];
  12. void init(int S){
  13. for (int i=0;i<m;i++)
  14. size[i]=0;
  15. for (int i=0;i<m;i++){
  16. fa[i]=(S>>(i+i+i)&7);
  17. size[fa[i]]++;
  18. }
  19. }
  20. void remark(){
  21. static int Min[9];
  22. for (int i=0;i<=m;i++) Min[i]=-1;
  23. for(int i=0;i<m;i++){
  24. if(Min[fa[i]]==-1) Min[fa[i]]=i;
  25. fa[i]=Min[fa[i]];
  26. }
  27. }
  28. bool test(int x,int y,bool up,bool left){
  29. //判断该种连接方式是否合法
  30. if (!x&&up) return 0;//连出边界
  31. if (!y&&left) return 0;//连出边界
  32. if (x&&!up&&size[fa[y]]==1) return 0;//上方的点孤立了
  33. if (up&&left){
  34. if (fa[y-1]==fa[y]) return 0;//成环
  35. int S=fa[y];fa[y]=fa[y-1];
  36. for (int i=0;i<m;i++)
  37. if (fa[i]==S) fa[i]=fa[y-1];
  38. remark();
  39. return 1;
  40. }
  41. if (up) return 1;
  42. if (left) fa[y]=fa[y-1];
  43. else fa[y]=m;
  44. remark();
  45. return 1;
  46. }
  47. int val(){
  48. int S=0;
  49. for (int i=0;i<m;i++) S|=fa[i]<<(i+i+i);
  50. return S;
  51. }
  52. void print(){
  53. for (int i=0;i<m;i++) printf("%d ",fa[i]);
  54. }
  55. };
  56. const int N=1e6+10;
  57. struct hash_map{
  58. int q[N],val[N],key[N],size;
  59. hash_map(){memset(key,-1,sizeof key);}
  60. int hash(int x){
  61. int ans=0;
  62. for (int i=x;i;i/=13) ans=ans*23+i%13;
  63. ans%=N;
  64. if (ans<0) ans+=N;
  65. while (key[ans]!=-1&&key[ans]!=x) ans==N-1?ans=0:ans++;
  66. return ans;
  67. }
  68. bool count(int x){
  69. return key[hash(x)]!=-1;
  70. }
  71. int& operator [] (int x){
  72. int ans=hash(x);
  73. if (key[ans]==-1){
  74. key[ans]=x;
  75. q[++size]=ans;
  76. val[ans]=0;
  77. }
  78. return val[ans];
  79. }
  80. void clear(){
  81. while (size) key[q[size--]]=-1;
  82. }
  83. };
  84. typedef pair<int,int> pii;
  85. struct table{
  86. hash_map M;
  87. //map<int,int> M;
  88. vector<pii> v;//first表示其状态,second为方案数
  89. void clear(){
  90. M.clear();
  91. v.clear();
  92. }
  93. void insert(int S,int k){//给S状态方案数+k
  94. if (!M.count(S)){
  95. M[S]=v.size();
  96. v.push_back(pii(S,k));
  97. }
  98. else{
  99. int &val=v[M[S]].second;
  100. val=inc(val,k);
  101. }
  102. }
  103. int val(int S){
  104. if (!M.count(S)) return 0;
  105. return v[M[S]].second;
  106. }
  107. }dp[2],*x=&dp[0],*y=&dp[1];
  108. bool left_edge[210][20],up_edge[210][20];
  109. void extend(int i,int j){
  110. y->clear();
  111. state S,T;
  112. for (int a=0;a<x->v.size();a++){
  113. S.init(x->v[a].first);
  114. int val=x->v[a].second;
  115. for (int up=up_edge[i][j];up<=1;up++)
  116. for (int left=left_edge[i][j];left<=1;left++){
  117. T=S;
  118. if (T.test(i,j,up,left))
  119. y->insert(T.val(),val);
  120. }
  121. }
  122. swap(x,y);
  123. /*printf("add (%d,%d)\n",i,j);
  124. for (int i=0;i<x->v.size();i++){
  125. S.init(x->v[i].first);
  126. S.print();
  127. printf("cases: %d\n",x->v[i].second);
  128. }*/
  129. }
  130. int main()
  131. {
  132. freopen("treeinagrid.in","r",stdin);
  133. freopen("treeinagrid.out","w",stdout);
  134. scanf("%d",&T);
  135. while (T--){
  136. scanf("%d%d%d",&n,&m,&mod);
  137. memset(s,0,sizeof s);
  138. for (int i=0;i<n*2-1;i++) scanf("%s",s[i]);
  139. for (int i=0;i<n;i++)
  140. for (int j=0;j<m;j++){
  141. left_edge[i][j+1]=(s[i<<1][j<<1|1]=='-');
  142. up_edge[i+1][j]=(s[i<<1|1][j<<1]=='|');
  143. }
  144. x->clear();
  145. x->insert(0,1);
  146. for (int i=0;i<n;i++)
  147. for (int j=0;j<m;j++)
  148. extend(i,j);
  149. if (!x->M.count(0)) puts("Impossible");
  150. else printf("%d\n",x->val(0));
  151. }
  152. return 0;
  153. }