• 【USACO2.4】解题报告


    前言

    好久没有刷USACOUSACO的题目了。这个合集也咕咕咕了。
    最近终于从JZOJJZOJ和比赛中脱过身来,补一下坑。
    其实前面几道题好早就AA了,主要是最后一道模拟一直不想做。做了之后才发现挺简单的。也就用了洛谷的8个下载测试点而已。
    本章主要考察搜索+最短路。还是处于基础阶段。
    USACOUSACOhttp://train.usaco.org/


    2.4.2.The Tamworth Two

    思路:

    这道题没有什么好说的。直接按照题目所说的方法搜索下去即可。
    遇见障碍就拐弯,直到相遇为止。
    clock()clock()计算时间,若即将超时就输出00,极大的几率是无解的。


    代码:

    #include <cstdio>
    #include <ctime>
    #include <iostream>
    using namespace std;
    
    const int N=11;
    const int dx[]={0,-1,0,1,0};
    const int dy[]={0,0,1,0,-1};
    char map[N][N];
    int x,y,x1,y1,x2,y2,p1,p2,sum,Time;
    
    //北1
    //东2
    //南3  
    //西4
    
    int main()
    {
        Time=clock();  //计算时间
        for (int i=1;i<=10;i++)
        {
            cin>>map[i]+1;
            for (int j=1;j<=10;j++)
            {
                if (map[i][j]=='F')
                    x1=i,y1=j;
                if (map[i][j]=='C')
                    x2=i,y2=j;  //记录位置
            }
        }
        p1=p2=1;
        if (x1==x2&&y1==y2)
            return !printf("0
    ");
        sum=1;
        while (clock()-Time<950)  //超时就退出
        {
            x=x1+dx[p1],y=y1+dy[p1];
            if (x>0&&y>0&&x<11&&y<11&&map[x][y]!='*')
            {
                x1=x;
                y1=y;
            }
            else p1=p1%4+1;
            x=x2+dx[p2],y=y2+dy[p2];
            if (x>0&&y>0&&x<11&&y<11&&map[x][y]!='*')
            {
                x2=x;
                y2=y;
            }
            else p2=p2%4+1;
            if (x1==x2&&y1==y2) return !printf("%d
    ",sum);
            sum++;
        }
        printf("0
    ");
        return 0;
    }
    

    2.4.3.Shortest Paths

    思路:

    暴力广搜,直到走出去为止。
    注意细节。


    代码:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <queue>
    using namespace std;
    
    const int dx[]={0,0,0,-1,1};
    const int dy[]={0,-1,1,0,0};
    int n,m,ans=1;
    char map[310][310];
    bool vis[310][310];
    
    struct Map  //记录地图
    {
        queue<int> x,y;  //广搜队列
    }q;
    queue<int> dis;
    
    void bfs()  //广搜模板
    {
        while (q.x.size())
        {
            int x=q.x.front();
            int y=q.y.front();
            q.x.pop();
            q.y.pop();
            for (int i=1;i<=4;i++)
            {
                int xx=x+2*dx[i],yy=y+2*dy[i];
                if (map[x+dx[i]][y+dy[i]]!=' ') continue;
                if (vis[xx][yy]) continue;
                if (xx<1||xx>2*n||yy<1||yy>2*m) continue;
                vis[xx][yy]=1;
                q.x.push(xx);
                q.y.push(yy);
                dis.push(dis.front()+1);
                ans=max(ans,dis.back());
            }
            dis.pop();
        }
    }
    
    int main()
    {
        scanf("%d%d
    ",&m,&n);
        for (int i=1;i<=n*2+1;i++)
            gets(map[i]+1);
        for (int i=1;i<=n;i++)
        {
            if (map[i*2][1]==' ')
                q.x.push(i*2),q.y.push(2),dis.push(1);
            if (map[i*2][m*2+1]==' ')
                q.x.push(i*2),q.y.push(m*2),dis.push(1);  //注意建图细节
        }
        for (int i=1;i<=m;i++)
        {
            if (map[1][i*2]==' ')
                q.x.push(2),q.y.push(i*2),dis.push(1);
            if (map[n*2+1][i*2]==' ')
                q.x.push(n*2),q.y.push(i*2),dis.push(1);
        }
        bfs();
        printf("%d
    ",ans);
        getchar();getchar();
        return 0;
    }
    

    2.4.4.Cow Tours

    思路:

    先求出任意两点之间距离,在求两个联通快内的最长路径,然后枚举连接哪两个点i,ji,j,那么很明显答案就是max(max(距离ii最远点距离+i+ijj的距离++距离jj最远点距离,第一个联通块内的最长路径,第二个联通块内的最长路径))
    可以用FloydFloyd+并查集求。


    代码:

    #include <cstdio>
    #include <cmath>
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    const int N=200;
    const double Inf=1e9;
    int n,x[N],y[N],map[N][N],father[N];
    double dis[N][N],sum1,sum2,ans,maxn[N];
    
    double get_dis(double x1,double x2,double y1,double y2)  //求距离
    {
        return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
    }
    
    int find(int x)  //并查集
    {
        return x==father[x]?x:father[x]=find(father[x]);
    }
    
    int main()
    {
        ans=Inf;
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        {
            scanf("%d%d",&x[i],&y[i]);
            father[i]=i;
        }
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
            {
                scanf("%1d",&map[i][j]);
                if (map[i][j]==1)
                {
                    dis[i][j]=get_dis(x[i],x[j],y[i],y[j]);
                    father[find(j)]=find(i);
                }
                else dis[i][j]=Inf+1.0;
            }
        for (int k=1;k<=n;k++)  //Floyd
            for (int i=1;i<=n;i++)
                for (int j=1;j<=n;j++)
                    if (i!=j&&j!=k&&k!=i)
                        dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)  //块内最长路径
                if (find(i)==find(j)&&i!=j)
                    maxn[find(i)]=max(maxn[find(i)],dis[i][j]);
                    
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)  //选择ij连边
                if (i!=j&&find(i)!=find(j))
                {
                    sum1=0;
                    sum2=0;
                    for (int k=1;k<=n;k++)
                    {
                        if (find(i)==find(k)&&i!=k)
                            sum1=max(sum1,dis[i][k]);
                        if (find(j)==find(k)&&j!=k)
                            sum2=max(sum2,dis[j][k]);
                    }
                    ans=min(ans,max(sum1+sum2+get_dis(x[i],x[j],y[i],y[j]),max(maxn[find(i)],maxn[find(j)])));
                }
        printf("%6lf
    ",ans);
        return 0;
    }
    

    2.4.5.Bessie Come Home

    思路:

    最短路模板,没什么好说的。
    不卡SPFASPFA好评XD。


    代码:

    #include <iostream>
    #include <cstring>
    #include <queue>
    using namespace std;
    
    const int N=100;
    const int M=10010;
    int n,x,head[N],tot,vis[N],dis[N],ans,minn;
    char ch1,ch2;
    
    struct edge
    {
        int next,to,dis;
    }e[M*2];
    
    int pos(char c)  //给字母编号
    {
        if (c>='A'&&c<='Z') return c-'A'+1;
        return c-'a'+27;
    }
    
    void add(int from,int to,int dis)
    {
        e[++tot].to=to;
        e[tot].dis=dis;
        e[tot].next=head[from];
        head[from]=tot;
    }
    
    void spfa()
    {
        queue<int> q;
        q.push(26);
        memset(dis,0x3f3f3f3f,sizeof(dis));
        dis[26]=0;
        vis[26]=1;
        while (q.size())
        {
            int u=q.front();
            q.pop();
            vis[u]=0;
            for (int i=head[u];~i;i=e[i].next)
            {
                int v=e[i].to;
                if (dis[v]>dis[u]+e[i].dis)
                {
                    dis[v]=dis[u]+e[i].dis;
                    if (!vis[v])
                    {
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
    }
    
    int main()
    {
        memset(head,-1,sizeof(head));
        cin>>n;
        for (int i=1;i<=n;i++)
        {
            cin>>ch1>>ch2>>x;
            add(pos(ch1),pos(ch2),x);
            add(pos(ch2),pos(ch1),x);
        }
        spfa();
        minn=2147483647;
        for (int i=1;i<=25;i++)
            if (head[i]!=-1&&dis[i]<minn)
            {
                minn=dis[i];
                ans=i;
            }
        cout<<(char)(ans+'A'-1)<<" "<<minn<<endl;
        return 0;
    }
    
    

    2.4.6.Fractions to Decimals

    思路:

    当除法进行到一段时间后,出现了商和余数与曾经的某一次完全一样的情况,那么就说明找到循环节了。
    那么就模拟下去,注意特判一些恶心的情况。
    **题我都不知道该说什么了。
    懒得打hashhash,用了mapmap水过去。


    代码:

    #include <cstdio>
    #include <map>
    #include <algorithm>
    #define mp make_pair
    using namespace std;
    
    int a,b,ans[200010],s,n,k;
    map<pair<int,int>,int> p;
    
    int len(int x)  //求整数部分长度
    {
    	if (x>9) return len(x/10)+1;
    	return 1;
    }
    
    int main()
    {
    	scanf("%d%d",&a,&b);
    	if (__gcd(a,b)==b)
    	{
    		printf("%d.0
    ",a/b);
    		return 0;
    	}
    	s=len(a/b)+1;  //+1是加上小数点的长度
    	printf("%d.",a/b);
    	a%=b;
    	while (1)
    	{
    		n++;
    		if (!a)
    		{
    			for (int i=1;i<n;i++)  //能除尽
    			{
    				s++;
    				printf("%d",ans[i]);
    				if (s%76==0) putchar(10);
    			}
    			putchar(10);
    			return 0;
    		}
    		a*=10;
    		if (p[mp(a/b,a%b)])  //判断是否出现过这种情况
    		{
    			k=p[mp(a/b,a%b)];
    			break;
    		}
    		p[mp(a/b,a%b)]=n;
    		ans[n]=a/b;
    		a%=b;
    	}
    	for (int i=1;i<n;i++)
    	{
    		if (i==k)
    		{
    			putchar('(');
    			s++;
    			if (s%76==0) putchar(10);
    		}
    		printf("%d",ans[i]);
    		s++;
    		if (s%76==0) putchar(10);
    	}
    	putchar(')');
    	putchar(10);
    }
    
  • 相关阅读:
    MongoDB索引使用
    ubuntu14.04下CPU的caffe配置,不成功的朋友请与我(lee)联系,后面附带邮箱
    android4.4 evaluateJavascript 到android2.X上不能调用的问题
    LeetCode122:Best Time to Buy and Sell Stock II
    Hdu-1565 方格取数(1) (状态压缩dp入门题
    TI C66x DSP 四种内存保护问题 -之- 针对CPU訪问外存(DDR3 or MSM)时的内存保护问题
    显示和隐藏Mac隐藏文件的命令
    【微软2014实习生及秋令营技术类职位在线測试】题目1 : String reorder
    钟表效果
    hibernate5(10)注解映射[2]一对多单向关联
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998377.html
Copyright © 2020-2023  润新知