• We need water!


    We need water!
    (water.c/cpp/pas)
    描述 Description
    这个岛可以用一根数轴来表示。这根数轴上某些地方有露水。 一开始每个地方的露水都
    是 同样多的。随着时间推移,露水会 不断蒸发。对于每一滴露水, 每一单位时间会使它失
    去一单位的水。莫诺现在在数轴的 0 位置上。他每单位时间可以走一单位距离。当他到达某
    一个露水的时候,他可以瞬间采集完该点的全部露水。动作的先后顺序是:采集 - 移动 - 露
    水蒸发 - 采集 - 移动„„。如果 0 位置有露珠,可以直接取。
    问莫诺最多能采集到多少露水。
    完成此题你将得到 100 分作为帮助莫诺的奖励。
    输入格式 Input Format
    第一行两个整数 n 和 m 表示有 n 个露水,每个露水一开始含有 m 单位水。
    接下来 n 行每行一个整数表示第 i 个露水的位置。
    输出格式 Output Format
    输出只有一行表示莫诺最多能采集到的水数。
    样例输入 Sample Input
    3 15
    6
    -3
    1
    样例输出 Sample Output
    25
    数据规模 Data Limitation
    100%的数据,1<=N<=300,
    1<=m<=1,000,000,-10,000<=x1,x2...xn<=10000。Xi≠Xj.

    【题解】

    这道题目和关路灯较为相似,但是我们还需要枚举取的露水的个数,然后在做类似关路灯的DP,f [ j ][ k ][ 0/1 ] 表示已经取了第j个~第k个露水,最后一次取露水是在j的位置 / k的位置时,所浪费掉(蒸发)的最少的水量,可以得到转移

    p表示枚举的露水个数,i 表示当前取的露水个数,j 和 k 枚举取的露水是第j个~第k个,可以得到转移:

    f[j][k][0] = min(f[j+1][k][0]+(a[j+1]-a[j]) * (p-i+1), f[j+1][k][1]+(a[k]-a[j])* (p-i+1));

    f[j][k][1] = min(f[j][k-1][1]+(a[k]-a[k-1]) * (p-i+1), f[j][k-1][0]+(a[k]-a[j])* (p-i+1));

    然后用p*m(总水量)- 最少的浪费掉的水量来更新ans。如果一开始0的位置没有露水,需要先添加一个露水,然后最后再减掉。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N=400;
    int n,m,a[N],f[N][N],g[N][N],ans=0;
    inline int max(int a,int b) {
        return a>b?a:b;
    }
    int main() {
        freopen("water.in","r",stdin);
        freopen("water.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++)
            scanf("%d",&a[i]);
        a[++n]=0;
        sort(a+1,a+1+n);
        int s;
        for(int i=1; i<=n; i++)
            if(a[i]==0) {
                s=i;
                break;
            }
        /*memset(f,0x3f,sizeof(f));
        memset(g,0x3f,sizeof(g));
        f[s][s]=g[s][s]=0;
        for(int len=2; len<=n; len++) {
            for(int i=1; i+len-1<=n; i++) {
                int j=i+len-1;
                f[i][j]=min(f[i+1][j]+(a[i+1]-a[i])*(n-len+1),g[i+1][j]+(a[j]-a[i])*(n-len+1));
                g[i][j]=min(g[i][j-1]+(a[j]-a[j-1])*(n-len+1),f[i][j-1]+(a[j]-a[i])*(n-len+1));
                ans=max(ans,(len-1)*m-min(f[i][j],g[i][j]));
            }
        }*/
        for(int p=1; p<=n; p++) {
            memset(f,0x3f,sizeof(f));
            memset(g,0x3f,sizeof(g));
            f[s][s]=g[s][s]=0;
            for(int len=2; len<=p; len++)
                for(int i=1; i+len-1<=n; i++) {
                    int j=i+len-1;
                    f[i][j]=min(f[i+1][j]+(a[i+1]-a[i])*(p-len+1),g[i+1][j]+(a[j]-a[i])*(p-len+1));
                    g[i][j]=min(g[i][j-1]+(a[j]-a[j-1])*(p-len+1),f[i][j-1]+(a[j]-a[i])*(p-len+1));
                    ans=max(ans,(len-1)*m-min(f[i][j],g[i][j]));
                }
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    设计模式之开篇(C#语法) 爱拼才会赢
    C#语法糖之第一篇:自动属性&隐式类型 爱拼才会赢
    C#语法糖之第四篇: 扩展方法 爱拼才会赢
    C#中this在扩展方法的应用
    笔记20120215_转义字符_运算符
    Linux基本操作
    SQL创表
    软件测试的概念
    java 线程池
    Redis广播
  • 原文地址:https://www.cnblogs.com/kcfzyhq/p/8568474.html
Copyright © 2020-2023  润新知