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
不管怎样,还是贴上代码:虽然有点慢。
代码
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 }