SGU 125 Shtirlits 搜索+可行性剪枝

500ms时限406ms水过……

直接枚举肯定超时,需要剪枝。

枚举每个格子的元素,检查其左上角和正上方格子是否满足条件,若不满足不必再向下搜索。

这里 看到一个更好的方法: 枚举每个格子是哪个相邻的比它大。然后DFS看看有没有环。这样的复杂度只有(2^5*3^5)。

不过我没写出来……而且也不太清楚这个时间复杂度是怎么算的……求指点!

 

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 
  5 const int dx[] = { -1, 1, 0, 0 };
  6 const int dy[] = { 0, 0, -1, 1 };
  7 
  8 int N;
  9 int mat[5][5];
 10 int G[5][5];
 11 
 12 bool check( int i, int j )
 13 {
 14     return i >= 0 && i < N && j >= 0 && j < N;
 15 }
 16 
 17 //wh=true 代表检查左上角格子是否满足条件, wh=false代表检查正上方格子
 18 bool ok( int x, int y, bool wh )
 19 {
 20     int cnt = 0;
 21     for ( int k = 0; k < 4; ++k )
 22     {
 23         int xx = x + dx[k];
 24         int yy = y + dy[k];
 25         if ( check( xx, yy ) && G[xx][yy] > G[x][y] ) ++cnt;
 26     }
 27 
 28     if ( wh ) return cnt == mat[x][y];
 29     return cnt <= mat[x][y];
 30 }
 31 
 32 bool Judge()
 33 {
 34     int cnt = 0;
 35 
 36     for ( int i = 0; i < N; ++i )
 37     {
 38         for ( int j = 0; j < N; ++j )
 39         {
 40             cnt = 0;
 41             for ( int k = 0; k < 4; ++k )
 42             {
 43                 int xx = i + dx[k];
 44                 int yy = j + dy[k];
 45                 if ( check( xx, yy ) )
 46                 {
 47                     if ( G[xx][yy] > G[i][j] )
 48                         ++cnt;
 49                 }
 50             }
 51             if ( cnt != mat[i][j] ) return false;
 52         }
 53     }
 54 
 55     return true;
 56 }
 57 
 58 bool DFS( int cur )
 59 {
 60     if ( cur == N * N )
 61     {
 62         if ( Judge() ) return true;
 63         return false;
 64     }
 65 
 66     int x = cur / N;
 67     int y = cur % N;
 68     for ( int i = 0; i < 10; ++i )
 69     {
 70         G[x][y] = i;
 71 
 72         bool okey = true;
 73 
 74         if ( check( x - 1, y - 1 ) )
 75         {
 76             if ( !ok( x - 1, y - 1, true ) )
 77                 okey = false;
 78         }
 79 
 80         if ( okey && check( x - 1, y ) )
 81         {
 82             if ( !ok( x - 1, y, false ) )
 83                 okey = false;
 84         }
 85 
 86         if ( okey )
 87         {
 88             if ( DFS( cur + 1 ) )
 89                 return true;
 90         }
 91 
 92         G[x][y] = -1;
 93     }
 94 
 95     return false;
 96 }
 97 
 98 int main()
 99 {
100     //freopen( "s.out", "w", stdout );
101     while ( scanf( "%d", &N ) == 1 )
102     {
103         for( int i = 0; i < N; ++i )
104             for( int j = 0; j < N; ++j )
105                 scanf( "%d", &mat[i][j] );
106 
107         memset( G, -1, sizeof( G ) );
108         if ( DFS( 0 ) )
109         {
110             for ( int i = 0; i < N; ++i )
111             {
112                 for ( int j = 0; j < N; ++j )
113                 {
114                     if ( j ) putchar(' ');
115                     printf( "%d", G[i][j] );
116                 }
117                 puts("");
118             }
119         }
120         else puts("NO SOLUTION");
121     }
122     return 0;
123 }

 

posted @ 2013-07-25 20:42  冰鸮  阅读(361)  评论(0编辑  收藏  举报