zoukankan      html  css  js  c++  java
  • P2905 [USACO08OPEN]农场危机Crisis on the Farm

    传送门

    DP

    设 f [ i ] [ j ] [ k ] 表示已经走了 i 步,向上走了 j 步,向右走了 k 步时能拯救的最多奶牛数(j,k可以为负,表示反向)

    设 g [ i ] [ j ] 表示牛向上走 i 步,向右走 j 步后有多少奶牛恰好在草堆上(同样 i , j 可负)

    那么 f [ i ] [ j ] [ k ] = max( f [ i-1 ] [ j -1 ] [ k ] , f [ i-1 ] [ j ] [ k-1 ] , f [ i-1 ] [ j+1 ] [ k ] ,f [ i-1 ] [ j ] [ k+1 ]) +g [ j ] [ k ]

    因为数组下标不能为负,所以要把坐标集体加上一个 K

    为了方便按字典序输出,我们要倒过来推,并且要按字典序的方向来枚举

    即从 f [ k ] 推到 f [ 0 ] 枚举方向为 'E' 'N' 'S' 'W'

    好像不太好讲,具体还是看代码吧,代码不难的

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=1007,K=31;
    int n,m,k;
    int xx[4]={1,0,0,-1},yy[4]={0,1,-1,0};
    char mp[4]={'E','N','S','W'};
    int f[K<<1][N][N],g[K<<1][K<<1];
    int cow[N][2],hay[N][2];
    int main()
    {
        n=read(); m=read(); k=read();
        for(int i=1;i<=n;i++) cow[i][0]=read(),cow[i][1]=read();
        for(int i=1;i<=m;i++) hay[i][0]=read(),hay[i][1]=read();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(abs(hay[j][0]-cow[i][0])+abs(hay[j][1]-cow[i][1])<=k)//如果可以到达才计算贡献
                    g[hay[j][0]-cow[i][0]+K][hay[j][1]-cow[i][1]+K]++;//预处理g
        for(int i=k;i>=0;i--)
            for(int x=K-i;x<=K+i;x++)
                for(int y=K-i;y<=K+i;y++)//注意大小写K的区别
                {
                    for(int o=0;o<4;o++) f[i][x][y]=max(f[i][x][y],f[i+1][x+xx[o]][y+yy[o]]);
                    f[i][x][y]+=g[x][y];
                }
        printf("%d
    ",f[0][K][K]);
        int posx=K,posy=K;//存当前位置
        for(int i=0;i<k;i++)
        {
            int o;
            for(o=0;o<4;o++) if(f[i][posx][posy]==f[i+1][posx+xx[o]][posy+yy[o]]+g[posx][posy]) break;//如果是从o推过来的就断开
            posx+=xx[o]; posy+=yy[o];
            printf("%c",mp[o]);
        }
        return 0;
    }
  • 相关阅读:
    Windows netstat 查看端口、进程占用
    nginx开启gzip
    linux查看内存
    linux查看进程、端口
    linux查看磁盘信息
    vmware克隆一台机器后修改etho
    java对象访问
    学生基本信息管理
    作业09-异常
    博客作业06--图
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/9860524.html
Copyright © 2011-2022 走看看