ZOJ 1008 题解

    题目链接:http://acm.zju.edu.cn/show_problem.php?pid=1008

    记得做这个题目的时候想了好久,代码重写了好几次,每次都是优化做的不好,直接超时,10s的时间限制已经很长了,还是超了。

    题目的大概意思是,n*n个方块纸,然后纸的四个方向上面都有数字,现在问的是能不能组合一下这样的纸,使得相邻两张纸之间的数字是相同的。

    看到这个题目觉得应该是DFS做的,但是要是不做优化应该会超时,于是试了一下,果然超时,后来发现其实原来的算法本身就是错的,更别说超不超时了,即使 不超时也是错的,于是把一模一样的纸记在一起,cnt[i],据说这样会好一些,再据说这样是为了防止

1 1 1 1

1 1 1 1

1 1 1 1

2 2 2 2

这样的出现,又据说在测试数据中有很大的这样的数据,于是这样做了优化,其他就是直接的DFS,没有什么好的优化,论坛上说一张纸上四个数字都相同 也能做优化,不过还没理解,T_T

不管怎样,还是贴上代码:虽然有点慢。


ExpandedBlockStart.gif 代码
 1  #include < iostream >
 2  #include < cstdio >
 3  using   namespace  std ;
 4 
 5  int  b[ 25 ][ 4 ] ;
 6  int  cnt[ 25 ] ;
 7  int  n ;
 8  int  t ;
 9  int  found ;
10  int  put[ 25 ] ;
11  void  search( int  pos)
12  {
13  if (found  ==   0   &&  pos  ==  n  *  n)
14  {
15     found  =   1  ;
16      return  ;
17  }
18  else   if (found  ==   0 )
19  {
20      for ( int  i  =   0  ; i  <  t ; i  ++ )
21     {
22       if (cnt[i]  &&  (pos  %  n  ==   0   ||  b[put[pos  -   1 ]][ 1 ==  b[i][ 3 ])  &&  (pos  -  n  <   0   ||  b[put[pos  -  n]][ 2 ==  b[i][ 0 ]))
23      {
24       put[pos]  =  i ;
25       cnt[i]  --  ;
26       search(pos  +   1 ) ;
27       cnt[i]  ++  ;
28      }
29     
30     }
31  }
32  }
33  int  isequal( int  i ,  int  j)
34  {
35  if (b[i][ 0 ==  b[j][ 0 &&  b[i][ 1 ==  b[j][ 1 &&  b[i][ 2 ==  b[j][ 2 &&  b[i][ 3 ==  b[j][ 3 ])
36      return   1  ;
37  return   0  ;
38  }
39  int  main()
40  {
41  int  cases  =   1  ;
42  int  flag  =   0  ;
43  int  k ;
44  while ( 1 )
45  {
46     scanf( " %d " & n) ;
47      if (n  ==   0 )
48       break  ;
49     memset(cnt ,  0  ,  sizeof (cnt)) ;
50     t  =   0  ;
51      for ( int  i  =   0  ; i  <  n  *  n ; i  ++ )
52     {
53       for ( int  j  =   0  ; j  <   4  ; j  ++ )
54       scanf( " %d " & b[t][j]) ;
55       for (k  =   0  ; k  <  t ; k  ++ )
56        if (isequal(t , k))
57       {
58        cnt[k]  ++  ;
59         break  ;
60       }
61       if (k  ==  t)
62      {
63       cnt[t]  ++  ;
64       t  ++  ;
65      }
66     }
67     found  =   0  ;
68     search( 0 ) ;
69      if (flag)
70      printf( " \n " ) ;
71      if (found)
72      printf( " Game %d: Possible\n " , cases  ++ ) ;
73      else  printf( " Game %d: Impossible\n " , cases  ++ ) ;
74     flag  =   1  ;
75  }
76  return   0 ;
77  }


转载于:https://www.cnblogs.com/vivyli/archive/2010/02/05/1664073.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值