poj 3271 LilyPad

25 篇文章 0 订阅
17 篇文章 0 订阅

神坑。一上午全奉献给了他。哭。

还在还坑过了 神刚,大夫。心满意足。

题目大意:Bessie在一片池塘里面玩,FJ希望Bessie从标有3的格子跳到标有4的格子里面去。0表示水面,1表示极其结实的转基因荷叶,2表示更结实的大石头。3和4处都有荷叶。Bessie和国际象棋里面的骑士(也就是马啦)走法一致,都是向一个方向走两格,再拐弯一格。现在,Bessie只能在荷叶上面跳,水面上可以放荷叶。问Bessie从3走到4,至少要再放多少荷叶,以及在这个前提下有多少种放法。

所以基本思路 搜索 从起点到原点的路径 是水面的就加1。

所以稍微处理了一下,预处理每一个点的需要加1个荷叶的点。1个就好

然后从原点bfs一遍,遇到可以更新的点即 长度大于新的。就把ans从新赋值并且push进去,如果等于就ans【v】+=ans【u】

所以puts答案就好了。
上午一支不对主要在于。一开始的荷叶处理,我想dfs的搜就有可能绕远了,但是其实每个点是可以重复经过的。可是不加vis就会跪。不如循环着 预处理一下每一个点

代码不丑也不是很长

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#define ll long long
using namespace std;
//by mars_ch
int n,m;
int map[35][35],vis[35][35],dis[1005],inq[1005],pre[1005],g[35][35];
ll ans[1005];
int sx,sy,ex,ey;
int dx[8]={2,2,1,1,-1,-1,-2,-2};
int dy[8]={1,-1,-2,2,2,-2,-1,1}; 
struct data
{
    int f,t,nxt;
    int w;
}e[100005];
int first[1005],tot;
struct node
{
    int f,t,nxt;
    int w;
}bian[100005];
int head[1005],tol;
void add(int a,int b,int c)
{
    e[tot].f=a;
    e[tot].t=b;
    e[tot].w=c;
    e[tot].nxt=first[a];
    first[a]=tot++;
}
void bfs(int x,int y)
{
    memset(g,0,sizeof(g));
    queue<pair<int,int > > q;
    q.push(make_pair(x,y));
    g[x][y]=1;
    while(!q.empty())
    {
        pair<int,int> P=q.front();
        q.pop();

        for(int i=0;i<8;i++)
        {
            int nx=P.first+dx[i],ny=P.second+dy[i];
            if(nx<=0 || ny<=0 || ny>m || nx>n) continue;
            if(g[nx][ny]) continue;
            g[nx][ny]=1;
            if(map[nx][ny] == 1) q.push(make_pair(nx,ny));
            else 
            {
                //printf("%d %d\n",(x-1)*m+y,(nx-1)*m+ny); 
                add((x-1)*m+y,(nx-1)*m+ny,1);
            }
         } 
    }

}
void spfa(int src)
{
    memset(dis,0x3f,sizeof(dis));
    dis[src]=0;
    queue<int> q;
    q.push(src);
    ans[src]=1LL;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        if(pre[u] == 2) continue;
        for(int i=first[u];i!=-1;i=e[i].nxt)
        {
            int v=e[i].t;
            //printf("%d %d\n",u,e[i].t);
            if(dis[v]>dis[u]+e[i].w)
            {
                dis[v]=dis[u]+e[i].w;
                ans[v]=ans[u];
                q.push(v); 
            }
            else if(dis[v] == dis[u]+e[i].w)
            {
                ans[v]+=ans[u];
            }
        //  printf("answer is %d\n",ans[v]); 
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            scanf("%d",&map[i][j]);
            pre[(i-1)*m+j]=map[i][j];
            if(map[i][j] == 3) sx=i,sy=j;
            if(map[i][j] == 4) ex=i,ey=j;
        }
    } 
    memset(first,-1,sizeof(first));
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            bfs(i,j);
        }
    }
    bfs(sx,sy);//罪魁祸首 在这里。。。。。。。。。。把原点又走了一遍、、、qaq 
    spfa((sx-1)*m+sy);
    int ed=(ex-1)*m+ey;
    int res=dis[ed];
    if(dis[ed] == 1061109567)
    {
        printf("-1\n");
        return 0;
    }
    printf("%d\n",res-1);
    printf("%lld\n",ans[ed]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值