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 }


posted on 2010-02-05 01:56  vivy  阅读(646)  评论(0编辑  收藏  举报