POJ:3616-Milking Time

Milking Time

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 12324 Accepted: 5221

Description

Bessie is such a hard-working cow. In fact, she is so focused on maximizing her productivity that she decides to schedule her next N (1 ≤ N ≤ 1,000,000) hours (conveniently labeled 0..N-1) so that she produces as much milk as possible.

Farmer John has a list of M (1 ≤ M ≤ 1,000) possibly overlapping intervals in which he is available for milking. Each interval i has a starting hour (0 ≤ starting_houri ≤ N), an ending hour (starting_houri < ending_houri ≤ N), and a corresponding efficiency (1 ≤ efficiencyi ≤ 1,000,000) which indicates how many gallons of milk that he can get out of Bessie in that interval. Farmer John starts and stops milking at the beginning of the starting hour and ending hour, respectively. When being milked, Bessie must be milked through an entire interval.

Even Bessie has her limitations, though. After being milked during any interval, she must rest R (1 ≤ R ≤ N) hours before she can start milking again. Given Farmer Johns list of intervals, determine the maximum amount of milk that Bessie can produce in the N hours.

Input
  • Line 1: Three space-separated integers: N, M, and R
  • Lines 2..M+1: Line i+1 describes FJ’s ith milking interval withthree space-separated integers: starting_houri , ending_houri , and efficiencyi
Output
  • Line 1: The maximum number of gallons of milk that Bessie can product in the N hours
Sample Input

12 4 2
1 2 8
10 12 19
3 6 24
7 10 31

Sample Output

43


解题心得:

  1. 题意就是有m头牛,每一只牛有一个产奶的时间段和一个奶量,Bessie可以去给每一头奶牛挤奶,但是每次给一个奶牛挤奶之后必须休息R分钟,问Bessie选择怎么挤奶可以使挤出的奶最多。
  2. 最直观的的方法还是记忆化搜索,不用去推状态转移方程式,直接跟着题意走就行了。但是如果要推状态转移方程式就有很多种方法了,看过其他大佬最简单的方法就是按照每一只牛的时间段来转移,dp[i]表示按开始产奶的时间顺序处理第i头牛可以获得的最大的产奶量,转移方程可以从前面j头牛(如果第j头牛的时间符合)+第i头牛产的奶来更新dp[i]的最大值。其实这个状态转移就讲记忆化搜索提炼出来的公式,具体的看代码吧。

记忆化搜索的代码:

#include <algorithm>
#include <cstring>
#include <stdio.h>
using namespace std;
const int maxn = 1010;
int n,m,R;

struct COW {
    int l,r,va;
}cow[maxn];

long long dp[maxn*maxn];

bool cmp(COW a, COW b) {
    return a.l < b.l;
}

void init() {
    memset(dp,-1,sizeof(dp));
    scanf("%d%d%d",&n,&m,&R);
    for(int i=0;i<m;i++) {
        scanf("%d%d%d",&cow[i].l,&cow[i].r,&cow[i].va);
    }
    sort(cow,cow+m,cmp);
}

long long dfs(int num,int Time) {
    long long k0 = 0,k1 = 0;
    if(num >= m || Time >= n)
        return 0;
    if(dp[Time] != -1 && Time != -1)
        return dp[Time];
    if(cow[num].l >= Time && cow[num].r <= n) { //如果时间符合那就加上当前这头牛的产奶量
        k1 += dfs(num+1,cow[num].r+R) + cow[num].va;
    } else
        k1 += dfs(num+1,Time);//时间不符合直接检查下一头
    k0 += dfs(num+1,Time);
    return dp[Time] = max(k0,k1);
}

int main() {
    init();
    long long ans = dfs(0,-1);
    printf("%lld\n",ans);
    return 0;
}

提炼出状态转移的公式之后的代码:

#include <algorithm>
#include <stdio.h>
using namespace std;
const int maxn = 1010;
struct COW {
    int start_time,end_time,va;

    bool operator < (const COW &A) const {
        return A.start_time > start_time;
    }
}cow[maxn];

int dp[maxn];

int main() {
    int n,m,R;
    scanf("%d%d%d",&n,&m,&R);
    for(int i=1;i<=m;i++) {
        scanf("%d%d%d",&cow[i].start_time,&cow[i].end_time,&cow[i].va);
        cow[i].end_time += R;//实际结束的时间 = 结束时间 + 休息时间
    }

    sort(cow+1,cow+m+1);

    for(int i=1;i<=m;i++) {
        dp[i] = cow[i].va;
        for(int j=1;j<i;j++) {
            if(cow[j].end_time <= cow[i].start_time)
                dp[i] = max(dp[i],dp[j] + cow[i].va);
        }
    }

    int ans = 0;
    for(int i=0;i<=m;i++)
        ans = max(ans,dp[i]);
    printf("%d\n",ans);

    return 0;
}

转载于:https://www.cnblogs.com/GoldenFingers/p/9107115.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值