题目链接: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
不管怎样,还是贴上代码:虽然有点慢。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.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 }
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 }