• 洛谷P2905 [USACO08OPEN]农场危机Crisis on the Farm


    P2905 [USACO08OPEN]农场危机Crisis on the Farm

    题目描述

    约翰和他的奶牛组建了一只乐队“后街奶牛”,现在他们正在牧场里排练.奶牛们分成一堆 一堆,共1000)堆.每一堆里,30只奶牛一只踩在另一只的背上,叠成一座牛塔.牧场 里还有M(1 < M < 1000)个高高的草垛.

    作为出色的指挥家,约翰可以通过口哨指挥奶牛们移动.他的口哨有四个音,分别能使所有 的牛塔向东南西北四个方向移动一格.

    每一次,当一个牛塔到达了一个草垛所在的格子,牛塔最上方的奶牛就会跳到草垛上,而且 不再下来,而其他奶牛仍然呈塔状站在草垛所在的格子里.当牛塔只剩一只奶牛时,这只奶牛也 会跳到草垛上.

    突然,约翰大惊失色:原来邻家的奶缸爆炸了!滚滚而下的牛奶正朝着约翰的牧场冲来,不久就要将牧场淹没.约翰必须马上行动,用口哨声挽救奶牛们的生命.他要指挥奶牛尽量多地跳 上草操,草操上的奶牛将不会被淹死.

    约翰还有K次吹口哨的机会.那他最多还能救多少奶牛呢?请计算最多能挽救的奶牛数,以及 达到这个数目约翰需要吹的口哨调子序列.序列用E,W,S,N表示东西南北.如果有多种序列能达到 要求,输出作为字符串最小的.

    输入输出格式

    输入格式:
    • Line 1: Three space-separated integers: N, M, and K

    • Lines 2..N+1: Line i+1 describes the X,Y location of a stack of 30 cows using two space-separated integers: X_i and Y_i

    • Lines N+2..N+M+1: Line i+N+1 describes the X,Y location of a haystack using two space-separated integers: X_i and Y_i
    输出格式:
    • Line 1: A single integer that is the most number of cows that can be saved.

    • Line 2: K characters, the lexicographically least sequence of commands FJ should issue to maximize the number of cows saved.

    输入输出样例

    输入样例#1:
    3 6 3 
    3 4 
    6 2 
    5 7 
    8 2 
    9 2 
    6 4 
    5 4 
    6 7 
    8 7 
    
    输出样例#1:
    6 
    EEE 
    

    说明

    Use the 'east' whistle three times, at which point the milk floods the area. Each haystack ends up saving 1 cow.

    对于100%的数据,1le Kle 30,1le N,M,X_i,Y_ile 10001K30,1N,M,Xi​​,Yi​​1000

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define MAXN 1500
    using namespace std;
    int n,m,K,ans;
    int dx[4]={1,0,0,-1};
    int dy[4]={0,1,-1,0};
    char step[40][64][64];
    char C[4]={'W','S','N','E'};
    int cnt[64][64],f[40][64][64]; //f[k][i][j]记录走k步,纵向移动了i-31步,横向移动了j-31步,所能拯救的最多的牛的数量。
    int cawx[MAXN],cawy[MAXN],grassx[MAXN],grassy[MAXN];//记录牛和草垛的横纵坐标.
    int main(){
        scanf("%d%d%d",&n,&m,&K);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&cawx[i],&cawy[i]);
        for(int i=1;i<=m;i++)
            scanf("%d%d",&grassx[i],&grassy[i]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                int cx=cawx[i]-grassx[j];    //第i头牛移动到第j个草垛,纵向最少所走的距离.    
                int cy=cawy[i]-grassy[j];    //第i头牛移动到第j个草垛,横向最少所走的距离.
                if(abs(cx)<=30&&abs(cy)<=30)//因为k<=30,所以当有一个方向的距离大于30,就不用考虑了,因为一定不可能走到. 
                    cnt[cx+31][cy+31]++;    //否则cnt记录走纵向i步横向走j步所能拯救的牛的数量. 
            }
        for(int k=0;k<=K;k++)
            for(int i=0;i<=62;i++)
                for(int j=0;j<=62;j++){
                    f[k][i][j]=-0x3f3f3f3f;
                    step[k][i][j]='Z';
                }
        f[0][31][31]=cnt[31][31];    //赋初值,最开始时所能拯救的牛的数量为0. 
        //这里要理解,因为他可以向上下左右走,为了防止负坐标的出现,我们把一开始时的原点坐标当做(31,31).
        for(int k=1;k<=K;k++)
            for(int i=1;i<=61;i++)
                for(int j=1;j<=61;j++)
                    f[k][i][j]=cnt[i][j]+max(max(f[k-1][i-1][j],f[k-1][i+1][j]),max(f[k-1][i][j-1],f[k-1][i][j+1]));
                    //这个状态转移方程就不用解释了,还是很容易理解的. 
        for(int i=1;i<=61;i++)
            for(int j=1;j<=61;j++)
                ans=max(ans,f[K][i][j]);
        for(int i=1;i<=61;i++)
            for(int j=1;j<=61;j++)
                if(ans==f[K][i][j])
                    step[K][i][j]='A';    //如果为纵向走i步横向走j步是一种可行的走法,记录以方便求字典序最小. 
        for(int k=K-1;k>=0;k--)
            for(int i=1;i<=61;i++)
                for(int j=1;j<=61;j++)
                    for(int l=0;l<4;l++)
                        if(f[k][i][j]+cnt[i+dx[l]][j+dy[l]]==f[k+1][i+dx[l]][j+dy[l]]&&step[k+1][i+dx[l]][j+dy[l]]<'Z')
                            step[k][i][j]=C[l];    //倒序找出所有可能的走法. 
        cout<<ans<<endl;
        int i=31,j=31;
        for(int k=0;k<K;k++){
            cout<<step[k][i][j];
            if(step[k][i][j]=='E')    i--;    //找字典序最小的. 
            else if(step[k][i][j]=='W')    i++;
            else if(step[k][i][j]=='S')    j++;
            else if(step[k][i][j]=='N')    j--;    
        }
    }
  • 相关阅读:
    docker 批量删除
    ML
    hdu 1465:不容易系列之一(递推入门题)
    sdut 2162:The Android University ACM Team Selection Contest(第二届山东省省赛原题,模拟题)
    sdut 2163:Identifiers(第二届山东省省赛原题,水题)
    hdu 2108:Shape of HDU(计算几何,判断多边形是否是凸多边形,水题)
    hrbustoj 1545:基础数据结构——顺序表(2)(数据结构,顺序表的实现及基本操作,入门题)
    hdu 1312:Red and Black(DFS搜索,入门题)
    hrbustoj 1429:凸多边形(计算几何,判断点是否在多边形内,二分法)
    poj 1113:Wall(计算几何,求凸包周长)
  • 原文地址:https://www.cnblogs.com/thmyl/p/7526666.html
Copyright © 2020-2023  润新知