usaco之lilypad 大合集!集合poj 3271 bzoj 1632

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

呜咕~~今天有考试了。
先来反思一下。
1.第一题,思路很简单的模拟。。但是由于 一开始智障存的int取代了本来该有的都double导致 调了很久。还是缺根弦。
2.很简单的判断寻找的点是否在路径上的方法没有想到。而且其实并没有很深刻的理解。。
3.暂时不知道

所以我们来说一下 题目这两道题:
第一道:
poj 3271 其实这个原来 写过题解了。。这会放一起再对比一遍。。
第二道:
bzoj 1632

题意:
第一道:
这里写图片描述
这里写图片描述

第二道:
Farmer John 建造了一个美丽的池塘,用于让他的牛们审美和锻炼。这个长方形的池子被分割成了 M 行和 N 列( 1 ≤ M ≤ 30 ; 1 ≤ N ≤ 30 ) 正方形格子的 。某些格子上有惊人的坚固的莲花,还有一些岩石,其余的只是美丽,纯净,湛蓝的水。 贝茜正在练习芭蕾舞,她从一个莲花跳跃到另一个莲花,当前位于一个莲花。她希望在莲花上一个一个的跳,目标是另一个给定莲花。她能跳既不入水,也不到一个岩石上。 令门外汉惊讶的是,贝茜的每次的跳跃像中国象棋的马一样:横向移动1,纵向移动2,或纵向移动1,横向移动2。贝茜有时可能会有多达8个选择的跳跃。 Farmer John 在观察贝茜的芭蕾舞联系,他意识到有时候贝茜有可能跳不到她想去的目的地,因为路上有些地方没有莲花。于是他想要添加几个莲花使贝茜能够完成任务。一贯节俭的Farmer John想添加最少数量的莲花。当然,莲花不能放在石头上。 请帮助Farmer John确定必须要添加的莲花的最少数量。在添加的莲花最少基础上,算出贝茜从起始点跳到目标点需要的最少的步数。最后,还要算出满足添加的莲花的最少数量时,跳跃最少步数的跳跃路径的条数。

所以 找不同?哪里不一样呢?

1.第一道有2问,第二道3问。【【这不废话吗哈哈】】
2.第一道问的方案数是荷叶摆放的方案数,注意是摆放方案数,第二道是跳跃路径的方案数并且还是在2个优先级条件的情况下。。

分析即题解:

是有差别的两种方案问法相对应的有不同解法。
一定要把握好这个才ok
这里写图片描述
就像此图 poj题的答案应该是1 因为只有一种摆放方式
但是bzoj呢就应该是 2种 因为在放的个数和路径长度都有限的情况 也是一样的

所以 针对第一道题。我们必须预先处理初第一种的连边情况 建图才ok

但是对于第二种 只用在spfa的松弛过程中智姐加判等于就ok

其实有个bug。。我一直以为不能两边spfa那么些我在想 怎么判断点在不在啊。。连dis[v]=dis[u]+1这种可以判的条件都忘了。

所以就解决了。相比之下第二个简单一些

代码:
第一道

#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;
}

第二道暂时还没有 明天po 。。

来了~~

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
//by mars_ch
int n,m;
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}; 
int map[105][105],vis[105][105],add[105][105],dis[105][105],inq[10005];
long long ans[105][105];
void bfs()
{
    memset(add,0x3f,sizeof(add));
    memset(dis,0x3f,sizeof(dis));
    add[sx][sy]=0,dis[sx][sy]=0;
    vis[sx][sy]=1;
    ans[sx][sy]=1;
    queue<pair<int,int > > q;
    q.push(make_pair(sx,sy));
    while(!q.empty())
    {
        pair<int,int> P=q.front();
        q.pop();
        vis[P.first][P.second]=0;

        for(int i=0;i<8;i++)
        {
            int nx=P.first+dx[i],ny=P.second+dy[i];
            if(nx<1 || ny<1 || nx>n || ny>m) continue;
            if(map[nx][ny] == 2) continue;
            int cnt=0;
            if(map[nx][ny]==0) cnt=1;
            if(add[nx][ny]>add[P.first][P.second]+cnt)
            {
                add[nx][ny]=add[P.first][P.second]+cnt;
                dis[nx][ny]=dis[P.first][P.second]+1;
                ans[nx][ny]=ans[P.first][P.second];
                if(!vis[nx][ny])
                {
                    vis[nx][ny]=1;
                    q.push(make_pair(nx,ny));
                }
            }
            else if(add[nx][ny]==add[P.first][P.second]+cnt)
            {
                if(dis[nx][ny]>dis[P.first][P.second]+1)
                {
                    dis[nx][ny]=dis[P.first][P.second]+1;
                    ans[nx][ny]=ans[P.first][P.second];
                    if(!vis[nx][ny])
                    {
                        vis[nx][ny]=1;
                        q.push(make_pair(nx,ny));
                    }
                }
                else if(dis[nx][ny] == dis[P.first][P.second]+1)
                {
                    ans[nx][ny]+=ans[P.first][P.second];
                    if(!vis[nx][ny])
                    {
                        vis[nx][ny]=1;
                        q.push(make_pair(nx,ny));
                    }
                }
            }
         } 
    }

}
int main()
{
    //freopen("lilypad.in","r",stdin);
    //freopen("lilypad.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            scanf("%d",&map[i][j]);
            if(map[i][j] == 3) sx=i,sy=j;
            if(map[i][j] == 4) ex=i,ey=j;
        }
     } 
     bfs();
     if(dis[ex][ey] == 1061109567)
     {
        printf("-1\n");
        return 0;
     }
     else
     {
        printf("%d\n%d\n%lld\n",add[ex][ey],dis[ex][ey],ans[ex][ey]);
     }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值