POJ 3669 Meteor Shower

暴力DFS。

有2个剪枝:

1.记录一下走到某一格的最小步数

2.走到安全地点马上return

WA点:安全地点坐标不一定在300以内!

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;

const int INF=0x7FFFFFFF;
const int maxn=300+10;
int m,ans;
int f[maxn][maxn],flag[maxn][maxn];
int dir[4][2]={
    {0,1},
    {0,-1},
    {1,0},
    {-1,0}
};


bool P(int a,int b,int cnt)
{
    if(a>=0&&a<=305&&b>=0&&b<=305&&flag[a][b]>cnt+1&&cnt+1<f[a][b]) return 1;
    return 0;
}

void dfs(int a,int b,int cnt)
{
    if(f[a][b]==INF) 
    {
        ans=min(ans,cnt);
        return;
    }
    for(int i=0;i<4;i++)
    {
        if(P(a+dir[i][0],b+dir[i][1],cnt))
        {
            flag[a+dir[i][0]][b+dir[i][1]]=cnt+1;
            dfs(a+dir[i][0],b+dir[i][1],cnt+1);
        }
    }
}

int main()
{
    while(~scanf("%d",&m))
    {
        for(int i=0;i<306;i++) for(int j=0;j<306;j++) flag[i][j]=f[i][j]=INF;
        for(int i=1;i<=m;i++) 
        {
            int xi,yi,ti; scanf("%d%d%d",&xi,&yi,&ti);
            f[xi][yi]=min(f[xi][yi],ti);
            for(int k=0;k<4;k++)
            {
                if(xi+dir[k][0]>=0&&xi+dir[k][0]<=305)
                    if(yi+dir[k][1]>=0&&yi+dir[k][1]<=305)
                        f[xi+dir[k][0]][yi+dir[k][1]]=min(f[xi+dir[k][0]][yi+dir[k][1]],ti);
            }
        }
        ans=INF;
        if(f[0][0]>0) 
        {
            flag[0][0]=0;
            dfs(0,0,0);    
        }
        if(ans==INF) ans=-1;
        printf("%d
",ans);
    }
    return 0;
}