洛谷p1717

https://www.luogu.com.cn/problem/P1717

题意:

image

思路1(动态规划):

考虑状态表示:dp[i][j],表示前i个中调了j小时的最大值,有两种转移方式,要么不调,要么调k分钟,所以转移方程是:dp[i][j]=max(dp[i][j],dp[i-1][j-t[i]-k]+k*f-sum(d))

题解:

const int N = 30, M = 1010;
int f[N], t[N], d[N];
int dp[N][M];
void solve() {
    int n, h;
    scanf("%lld%lld", &n, &h);
    h *= 60;
    for (int i = 1;i <= n;i++) scanf("%lld", &f[i]);
    for (int i = 1;i <= n;i++) { scanf("%lld", &d[i]); }
    for (int i = 1;i < n;i++) { scanf("%lld", &t[i]); t[i] *= 5; }
    int cost = 0;
    for (int i = 1;i <= n;i++) {
        for (int j = cost+5;j <= h;j += 5) {//假设当前层要钓鱼,那么最小的起始时间
            int sum = 0;//是cost+5,dp[i][cost]一定是0,
            for (int k = 1;k * 5 <= j;k++) {//枚举当前层钓鱼时间
                 if (j - t[i - 1] - k * 5 >= 0) {
                    dp[i][j] = max(dp[i][j], dp[i - 1][j - t[i - 1] - k * 5] + k * f[i] - sum);
                    sum += d[i] * k;
                }
            }
        }
        cost += t[i];
    }
    int ret = 0;//因为不一定在最后一个点结束,所以取所有状态的最值,
    for (int i = 1;i <= n;i++) {
        for (int j = 0;j <= h;j += 5) {
            ret = max(ret, dp[i][j]);
        }
    }
    printf("%lld\n", ret);
}

思路二(贪心):

因为每次走的所花费的时间是不可避免的,所以可以先减去走路所花费的时间,然后剩下的时间全部用来钓鱼,每次取出最大值,(相当于已经知道在某个点需要调多少分钟,而不是返回上一个点继续钓鱼)

题解:

struct T {
    int f, id;
    bool operator < (const T& t)const {
        //   return bool
        return f < t.f;
    }
}a[30];
int d[30], t[30];
void solve() {
    int n, h;
    scanf("%lld%lld", &n, &h);
    h *= 60;
    for (int i = 1;i <= n;i++) {
        auto& [x, y] = a[i];
        scanf("%lld", &x);
        y = i;
    }
    priority_queue<T> heap;
    for (int i = 1;i <= n;i++) { scanf("%lld", &d[i]); }
    for (int i = 1;i < n;i++) { scanf("%lld", &t[i]);t[i] *= 5; }
    int ret=0;
    auto clear=[&](){
        while(heap.size()) heap.pop();
    };
    for(int i=1;i<=n;i++){//枚举钓鱼终点;
        h-=t[i-1];
        clear();
        int cur=0;
        for(int j=1;j<=i;j++) heap.push(a[j]);//将终点前的每一个钓鱼点放入堆中取最大
        for(int j=5;j<=h;j+=5){
            auto [x,y] = heap.top();
            heap.pop();
            if(x>0) cur+=x;
            heap.push({x-d[y],y});
        }
        ret=max(ret,cur);
    }
    printf("%lld\n",ret);
}
posted @ 2021-11-01 00:00  指引盗寇入太行  阅读(92)  评论(0编辑  收藏  举报