您的位置:首页 > 其它

SGU 125 Shtirlits 搜索+可行性剪枝

2013-07-25 20:42 281 查看
500ms时限406ms水过……

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

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

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

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

#include <cstdio>
#include <cstring>
#include <cstdlib>

const int dx[] = { -1, 1, 0, 0 };
const int dy[] = { 0, 0, -1, 1 };

int N;
int mat[5][5];
int G[5][5];

bool check( int i, int j )
{
return i >= 0 && i < N && j >= 0 && j < N;
}

//wh=true 代表检查左上角格子是否满足条件, wh=false代表检查正上方格子
bool ok( int x, int y, bool wh )
{
int cnt = 0;
for ( int k = 0; k < 4; ++k )
{
int xx = x + dx[k];
int yy = y + dy[k];
if ( check( xx, yy ) && G[xx][yy] > G[x][y] ) ++cnt;
}

if ( wh ) return cnt == mat[x][y];
return cnt <= mat[x][y];
}

bool Judge()
{
int cnt = 0;

for ( int i = 0; i < N; ++i )
{
for ( int j = 0; j < N; ++j )
{
cnt = 0;
for ( int k = 0; k < 4; ++k )
{
int xx = i + dx[k];
int yy = j + dy[k];
if ( check( xx, yy ) )
{
if ( G[xx][yy] > G[i][j] )
++cnt;
}
}
if ( cnt != mat[i][j] ) return false;
}
}

return true;
}

bool DFS( int cur )
{
if ( cur == N * N )
{
if ( Judge() ) return true;
return false;
}

int x = cur / N;
int y = cur % N;
for ( int i = 0; i < 10; ++i )
{
G[x][y] = i;

bool okey = true;

if ( check( x - 1, y - 1 ) )
{
if ( !ok( x - 1, y - 1, true ) )
okey = false;
}

if ( okey && check( x - 1, y ) )
{
if ( !ok( x - 1, y, false ) )
okey = false;
}

if ( okey )
{
if ( DFS( cur + 1 ) )
return true;
}

G[x][y] = -1;
}

return false;
}

int main()
{
//freopen( "s.out", "w", stdout );
while ( scanf( "%d", &N ) == 1 )
{
for( int i = 0; i < N; ++i )
for( int j = 0; j < N; ++j )
scanf( "%d", &mat[i][j] );

memset( G, -1, sizeof( G ) );
if ( DFS( 0 ) )
{
for ( int i = 0; i < N; ++i )
{
for ( int j = 0; j < N; ++j )
{
if ( j ) putchar(' ');
printf( "%d", G[i][j] );
}
puts("");
}
}
else puts("NO SOLUTION");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: