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;
    }
  • 相关阅读:
    LeetCode Merge Two Sorted Lists 归并排序
    LeetCode Add Binary 两个二进制数相加
    LeetCode Climbing Stairs 爬楼梯
    034 Search for a Range 搜索范围
    033 Search in Rotated Sorted Array 搜索旋转排序数组
    032 Longest Valid Parentheses 最长有效括号
    031 Next Permutation 下一个排列
    030 Substring with Concatenation of All Words 与所有单词相关联的字串
    029 Divide Two Integers 两数相除
    028 Implement strStr() 实现 strStr()
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/9860524.html
Copyright © 2011-2022 走看看