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;
    }
  • 相关阅读:
    P1030 求先序排列 P1305 新二叉树
    spfa
    Clairewd’s message ekmp
    Cyclic Nacklace hdu3746 kmp 最小循环节
    P1233 木棍加工 dp LIS
    P1052 过河 线性dp 路径压缩
    Best Reward 拓展kmp
    Period kmp
    Substrings kmp
    Count the string kmp
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/9860524.html
Copyright © 2011-2022 走看看