UVa 225

题意

平面上有k个障碍点。从(0,0)点出发,第一次走1个单位,第二次走2个单位,……,第n次走n个单位,恰好回到(0,0)。要求只能沿着东南西北方向走,且每次必须转弯90°(不能沿着同一个方向继续走,也不能后退)。走出的图形可以自交,但不能经过障碍点

AC代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>

using namespace std;
#define mst(a) memset(a, 0, sizeof(a));
const char tn[] = "ensw";
const int maxn = 105;
int n, k, num;
const int dir[4][2] = {{1, 0}, {0, 1}, {0, -1}, {-1, 0}};
int G[2*maxn][2*maxn], vis[2*maxn][2*maxn], r[maxn], sum[25];

void init()
{
    sum[0] = 0;
    for( int i = 1; i <= 20; i++ )
        sum[i] = sum[i-1] + i;
}

bool judge( int x, int y, int d ){  //剪枝
    int dis = abs(x-105)+abs(y-105);
    if(dis > sum[n]-sum[d]) return false;
    return true;
}

void dfs( int f, int d, int x, int y )
{
    if(d==n)
    {
        if( x != 105 || y != 105 )
            return;
        for( int i = 0; i < n; i++ )
            printf("%c",tn[r[i]]);
        printf("
");
        num++;
        return;
    }
    for( int k = 0; k < 4; k++ ){
        if( k == f || k + f == 3 ) continue;   //不允许直走或后退
        int dx = x, dy = y;
        int flag = 1;
        for( int i = 1; i <= d+1; i++ ){
            dx += dir[k][0];
            dy += dir[k][1];
            if(G[dx][dy] || !judge(dx, dy, d)){
                flag = 0;
                break;
            }
        }
        if(flag && !vis[dx][dy]){
            vis[dx][dy] = 1;
            r[d] = k;
            dfs(k, d+1, dx, dy);
            vis[dx][dy] = 0;
        }
    }
    return;
}


int main()
{
    int T, a, b;
    init();
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n, &k);
        mst(G);
        mst(vis);
        while(k--){
            scanf("%d%d",&a,&b);
            a += 105, b += 105;
            if( a >= 0 && b >= 0 )
                G[a][b] = 1;
        }
        num = 0;
        dfs(-1, 0, 105, 105);
        printf("Found %d golygon(s).

",num);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/JinxiSui/p/9740590.html