bzoj1295: [SCOI2009]最长距离

很有趣的题啊。

看到n、m、T这么小,一开始还以为是插头DP。。。

结果实际上就是暴力枚举起点,然后往周围spfa,d数组记录经过的障碍数且不能超过T,跑完就判断可以到达那些点,暴力枚举,记录最大值

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const int dx[4]={-1,0,1,0};
const int dy[4]={0,1,0,-1};

int n,m,T;
int mp[110][110];

struct node
{
    int x,y;
}list[11000];
int d[110][110];
bool v[110][110];
double spfa(int stx,int sty)
{
    if(mp[stx][sty]>T)return 0;
    
    memset(d,63,sizeof(d));d[stx][sty]=mp[stx][sty];
    memset(v,false,sizeof(v));v[stx][sty]=true;
    list[1].x=stx;list[1].y=sty;
    
    int head=1,tail=2;
    while(head!=tail)
    {
        int x=list[head].x,y=list[head].y;
        for(int i=0;i<=3;i++)
        {
            int tx=x+dx[i],ty=y+dy[i];
            if(tx>0&&tx<=n&&ty>0&&ty<=m)
            {
                if(d[tx][ty]>d[x][y]+mp[tx][ty]&&d[x][y]+mp[tx][ty]<=T)
                {
                    d[tx][ty]=d[x][y]+mp[tx][ty];
                    if(v[tx][ty]==false)
                    {
                        v[tx][ty]=true;
                        list[tail].x=tx;list[tail].y=ty;
                        tail++;if(tail==10500)tail=1;
                    }
                }
            }
        }
        v[x][y]=false;
        head++;if(head==10500)head=1;
    }
    
    double ret=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(d[i][j]<=T)
                ret=max( ret,sqrt(double(stx-i)*double(stx-i)+double(sty-j)*double(sty-j)) );
    return ret;
}

char ss[110];
int main()
{
    scanf("%d%d%d",&n,&m,&T);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",ss+1);
        for(int j=1;j<=m;j++)
            mp[i][j]=ss[j]-'0';
    }
    
    double ans=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            double d=spfa(i,j);
            ans=max(ans,d);
        }
    printf("%.6lf\n",ans);
    return 0;
}

 

posted @ 2018-02-12 09:08  AKCqhzdy  阅读(121)  评论(0编辑  收藏  举报