USACO 2.4

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sugar_free_mint/article/details/84635750

洛谷 1518 两只塔姆沃斯牛 The Tamworth Two

洛谷题目链接
USACO题目链接

分析

同时模拟牛和FJ的行为判断即可


代码

/*
ID:lemondi1
LANG:C++
TASK:ttwo
*/
#include <cstdio>
#define rr register
using namespace std;
struct site{int x,y,dir;}cow,john;
const int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
char s[12][12]; int ans,v[11][11][11][11];
signed main(){
    freopen("ttwo.in","r",stdin);
    freopen("ttwo.out","w",stdout);
    for (rr int i=1;i<11;++i) scanf("%s",s[i]+1);
    for (rr int i=0;i<12;++i) s[0][i]=s[11][i]=42;
    for (rr int i=1;i<11;++i) s[i][0]=s[i][11]=42;
    for (rr int i=1;i<11;++i)
    for (rr int j=1;j<11;++j)
    if (s[i][j]=='C') cow=(site){i,j,0};
        else if (s[i][j]=='F') john=(site){i,j,0};
    while (cow.x!=john.x||cow.y!=john.y){
        if (++v[cow.x][cow.y][john.x][john.y]==5) return !printf("0\n"); ++ans;
        if (s[cow.x+dx[cow.dir]][cow.y+dy[cow.dir]]==42) cow.dir=(cow.dir+1)%4; else cow.x+=dx[cow.dir],cow.y+=dy[cow.dir];
        if (s[john.x+dx[john.dir]][john.y+dy[john.dir]]==42) john.dir=(john.dir+1)%4; else john.x+=dx[john.dir],john.y+=dy[john.dir];
    }
    return !printf("%d\n",ans);
}

洛谷 1519 穿越栅栏 Overfencing

题目

问迷宫内的点到两个出口的最长的最短路


分析

一个一个肯定会超时,于是可以在两个出口进行深搜或者广搜,求出最长的答案,虽然讲得好像很简单,但是对于奇葩数据简直就是撞墙,关键是输入比较坑


代码

/*
ID:lemondi1
LANG:C++
TASK:maze1
*/
#include <cstdio>
#include <queue>
#define rr register
using namespace std;
const int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
struct node{int x,y,w;}; queue<node>q;
int n,m,ans; bool v[111][51][4],vis[111][51];
signed main(){
    freopen("maze1.in","r",stdin);
    freopen("maze1.out","w",stdout);
    scanf("%d%d",&m,&n);
    rr char c=getchar();
    while (c=='\r'||c=='\n') c=getchar();
    for (rr int i=1;i<2*n+2;++i)//处理输入的边,难度比较大
    if (i&1){
        while (c!='+') c=getchar();
        for (rr int j=1;j<=m;++j)
            v[i>>1][j][2]=v[(i+1)>>1][j][0]=getchar()==' ',
            getchar();
        getchar();
    }
    else{
        c=getchar();
        while (c=='\r'||c=='\n') c=getchar();
        for (rr int j=1;j<=m;++j)
            v[i>>1][j-1][1]=v[i>>1][j][3]=c==' ',
            getchar(),c=getchar();
        v[i>>1][m][1]=v[i>>1][m+1][3]=c==' ';
        while (c!='\r'&&c!='\n') c=getchar();
    }
    for (rr int i=1;i<=n;++i){//处理两个出口的位置
        if (v[i][1][3]) q.push((node){i,1,1}),vis[i][1]=1;
        if (v[i][m][1]) q.push((node){i,m,1}),vis[i][m]=1;
    }
    for (rr int i=2;i<m;++i){
        if (v[1][i][0]) q.push((node){1,i,1}),vis[1][i]=1;
        if (v[n][i][2]) q.push((node){n,i,1}),vis[n][i]=1;
    }
    while (q.size()){//普通的广搜
        rr int x=q.front().x,y=q.front().y,w=q.front().w;
        q.pop(); ans=ans>w?ans:w;
        for (rr int k=0;k<4;++k)
        if (v[x][y][k]){
            rr int rx=x+dx[k],ry=y+dy[k];
            if (vis[rx][ry]||rx<1||ry<1||rx>n||ry>m) continue;//要判断边界!
            q.push((node){rx,ry,w+1}); vis[rx][ry]=1;
        }
    }
    printf("%d\n",ans);
    return 0;
} 

洛谷 1522 牛的旅行 Cow Tours

题目

加入一条连接两个连通块的边,使两个连通块之间的点的最长路径最小


分析

首先可以先跑一次floyd,求出每个连通块内部的最短距离,然后依次访问没有加入的边,求出最小值,并与原先的最大结果做比较


代码

/*
ID:lemondi1
LANG:C++
TASK:cowtour
*/
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#define w(t) ((t)*(t))
#define count(i,j) sqrt(w(x[i]-x[j])+w(y[i]-y[j]))
#define rr register
using namespace std;
int n,x[151],y[151]; double dis[151][151],maxx[151],ans;
inline signed iut(){
    rr int ans=0; rr char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
    return ans;
}
inline double min(double a,double b){return a<b?a:b;}
signed main(){
    freopen("cowtour.in","r",stdin);
    freopen("cowtour.out","w",stdout);
    n=iut(); memset(dis,0x6f,sizeof(dis));
    for (rr int i=1;i<=n;++i) x[i]=iut(),y[i]=iut(),dis[i][i]=0;
    for (rr int i=1;i<=n;++i)
    for (rr int j=1;j<=n;++j){
        rr char c=getchar();
        while (c!=48&&c!=49) c=getchar();
        if (c==49) dis[i][j]=count(i,j);
    }
    for (rr int k=1;k<=n;++k)//floyd
    for (rr int i=1;i<=n;++i)
    for (rr int j=1;j<=n;++j)
    dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
    for (rr int i=1;i<=n;++i)//找出连接i点的最长路径
    for (rr int j=1;j<=n;++j)
    if (dis[i][j]!=dis[0][1])
    maxx[i]=maxx[i]>dis[i][j]?maxx[i]:dis[i][j];
    for (rr int i=1;i<=n;++i) ans=ans>maxx[i]?ans:maxx[i];//先求一遍最大值
    rr double ans1=dis[0][1];
    for (rr int i=1;i<=n;++i)
    for (rr int j=1;j<=n;++j)
    if (dis[i][j]==dis[0][1])//当可以连接两个连通块时
    ans1=min(ans1,maxx[i]+count(i,j)+maxx[j]);//求最小值
    printf("%.6lf\n",ans>ans1?ans:ans1);
    return 0;
}

洛谷 1529 回家 Bessie Come Home

题目

裸的最短路


代码(dijkstra+堆优化)

/*
ID:lemondi1
LANG:C++
TASK:comehome
*/
#include <cstdio>
#include <queue>
using namespace std;
struct node{
    int y,w,next;
}e[20011];
struct rec{
    int x,d;
    bool operator <(const rec &t)const{
        return d<t.d;
    }
};
int m,n,k=1,dis[61],ls[61],vis[2001];
char ans=65; priority_queue<rec>q;
int main(){
    freopen("comehome.in","r",stdin);
    freopen("comehome.out","w",stdout);
    scanf("%d\n",&m);
    for (int i=1;i<=m;++i){
        char x,y; int w;
        scanf("%c %c %d\n",&x,&y,&w);
        if (!vis[x]) vis[x]=++n;
        if (!vis[y]) vis[y]=++n;
        e[++k]=(node){vis[y],w,ls[vis[x]]}; ls[vis[x]]=k;
        e[++k]=(node){vis[x],w,ls[vis[y]]}; ls[vis[y]]=k;
    }
    for (int i=0;i<=n;++i) dis[i]=707406378;
    q.push((rec){vis['Z'],0}); dis[vis['Z']]=0;
    while (q.size()){
        int x=q.top().x,d=q.top().d; q.pop();
        if (dis[x]!=d) continue;
        for (int i=ls[x];i;i=e[i].next)
        if (dis[x]+e[i].w<dis[e[i].y]){
            dis[e[i].y]=dis[x]+e[i].w;
            q.push((rec){e[i].y,dis[e[i].y]});
        }
    }
    for (char i='B';i<'Z';++i)
    if (dis[vis[i]]<dis[vis[ans]]) ans=i;
    printf("%c %d\n",ans,dis[vis[ans]]);
    return 0;
}

洛谷 1530 分数化小数 Fractions to Decimals

my blog


后续

没有后续

猜你喜欢

转载自blog.csdn.net/sugar_free_mint/article/details/84635750