UVA 225 Golygons (暴力+回溯+dfs)

题意:

一个人从(0,0)开始,每次走的长度是1,2,3...,每次走完一段,就必须向左或向右转,停留的点不能重复,并且不能经过障碍物;

现在给出最后一步走多远,以及障碍物的位置,求最后又走回(0,0)点的方法有几种,输出每种走法,还有走法总数;

代码:

#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define mod 1000000007
#define mem(a) memset(a,0,sizeof(a))

using namespace std;
//由于坐标可能出现负的,走到第20的时候总路程为210,所以设置limit为105
//给所有的坐标都加上limit,保证vis的可用性
const int maxn = 250 , inf = 0x3f3f3f3f , limit = 105 ;
//方向:0->西 1->北 2->南 3->西
//将他们按字典序排列,就可以按字典序输出
int dir[4][2]={{1,0},{0,1},{0,-1},{-1,0}};
char face[4] = {'e','n','s','w'};
int n,m,ans;
//step存路径,sum存总长度,vis为访问标记(-1为障碍物,0表示可以访问,1表示不能访问)
int step[50],sum[25],vis[maxn][maxn];

//剪枝
bool cant(int x,int y,int d,int f){
    //按照f方向一步一步走,如果此时的位置超过了limit,之后肯定就回不来了
    //或者出现障碍物
    //剪枝
    for(int i = 1 ; i <= d ;i ++ ){
        x+=dir[f][0];
        y+=dir[f][1];
        if(abs(x)>limit||abs(y)>limit) return true;
        if(vis[x+limit][y+limit]==-1) return true;
    }
    //剩余的步数走不到(0,0)剪枝
    if(abs(x)+abs(y)>sum[n]-sum[d]) return true;
    return false;
}
//第一个参数为x坐标,第二个为y坐标,第三个为需要走的距离,第四个为方向
void dfs(int x,int y,int d,int f){
    //符合条件,输出
    if(d>n){
        if(x==0&&y==0){
            for(int i = 1 ; i<= n; i++ ){
                printf("%c",face[step[i]]);
            }
            printf("\n");
            ans++;
        }
        return;
    }
    //向四个方向走
    for(int i = 0 ; i < 4 ; i ++ ){
        if(i==f||i+f==3) continue;//原来方向和反方向不能走
        int xx = x + dir[i][0] * d;
        int yy = y + dir[i][1] * d;
        if(cant(x,y,d,i)) continue;
        if(vis[xx+limit][yy+limit]) continue;
        vis[xx+limit][yy+limit] = 1;//设置标记
        step[d] = i ;
        dfs(xx,yy,d+1,i);
        vis[xx+limit][yy+limit] = 0;//清除标记
    }
}

int main(){
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    int T;
    //预处理到第i个城市的总路程
    sum[0] = 0;
    for(int i = 1 ; i <= 20 ; i++ )
        sum[i] = i + sum[i-1];
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&m);
        mem(vis);
        ans = 0;
        int a,b;
        //障碍物设为-1
        for(int i = 0 ; i < m ; i ++ ){
            scanf("%d %d",&a,&b);
            vis[a+limit][b+limit] = -1;
        }
        dfs(0,0,1,-1);
        printf("Found %d golygon(s).\n\n",ans);
    }
}

猜你喜欢

转载自blog.csdn.net/insist_77/article/details/80383436