UVa #225 Golygons (习题7-2)


脑残强迫症数学家进大观园,每次走上一次走的步数+1的时候就要左/右转。规定了谜之数字n之后,最后一次行进的步数必须等于n。还愣头青不会绕障碍(大概是处女座,觉得绕过之后走成的路径不完美),问题:如何正确的回家


因为谜之数字n最多20,根据小学算术1+2+...+20应该等于210,也就是说傻逼数学家一天之内走的路不会超过210,那么想要成功折返的话最多往一个方向走105步(实际应该小于105因为不可能一直走)。所以我开一个250*250的数组作为地图,起始点设为(110,110)。


因为要打印路径,又要字典序最小,自然又是dfs。貌似可以加入"不可能按时返回"剪枝,不过并不是必须。


Run Time: 1.548s

#define UVa  "7-2.225.cpp"

#include<cstring>
#include<cstdio>
#include<vector>

using namespace std;


//Global Variables.
int laststep, blkn;
int dir[2][4] = {{1, 0, 0, -1},{0, 1, -1, 0}};    //lexicographics: e, n, s, w
int dir_availability[5][4] = {{0,1,1,0},{1,0,0,1},{1,0,0,1},{0,1,1,0}, {1,1,1,1}};
char dirname[4] = {'e', 'n', 's', 'w'};
int step[25];
int vis[250][250];
int cnt;
int startx = 110, starty = 110;
/////

int dfs(int d, int x, int y, int direction) {
    if(d == laststep + 1) {
        if(x == startx && y == starty) {
            for(int i = 1; i < d; i ++)
                printf("%c", dirname[step[i]]);
            printf("\n");
            cnt ++;
        }
        else return 0;
    }
    else {

        if((laststep*laststep - d*d) / 2 < (x - 110 + y - 110)) return 0;

        for(int i = 0; i < 4; i ++) {
            int nx = x + dir[0][i] *d , ny = y + dir[1][i] * d;     //walking
            if(nx > 0 && nx < 250 && ny > 0 && ny < 250 && !vis[nx][ny] && dir_availability[direction][i]) {  //if you walked to the boundaries, there would be no hope to be back on time.
                int ok = 1;
                if(i == 0 || i == 3) for(int m = min(x,nx); m <= max(x,nx); m ++) {
                    if(vis[m][y] == -1) {      //way blocked.
                        ok = 0;
                        break;
                    }
                }
                else if(i == 1 || i == 2) for(int m = min(y,ny); m < max(y,ny); m ++) {
                    if(vis[x][m] == -1) {      //way blocked.
                        ok = 0;
                        break;
                    }
                }
                if(ok) {
                    vis[nx][ny] = 1;
                    step[d] = i;
                    dfs(d + 1, nx, ny, i);
                    vis[nx][ny] = 0;
                }
            }
        }
    }
}


int main() {
    int kase;
    scanf("%d", &kase);
    while(kase --) {
        cnt = 0;
        memset(vis, 0, sizeof(vis));
        vis[0][0] = 1;
        scanf("%d%d", &laststep, &blkn);
        while(blkn --) {
            int a, b;
            scanf("%d%d", &a, &b);
            vis[startx+a][starty+b] = -1;
        }
        dfs(1, startx, starty, 4);
        printf("Found %d golygon(s).\n\n", cnt);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值