[USACO08MAR]跨河River Crossing【背包DP】

题目描述

Farmer John is herding his N cows (1 <= N <= 2,500) across the expanses of his farm when he finds himself blocked by a river. A single raft is available for transportation.

FJ knows that he must ride on the raft for all crossings and that that adding cows to the raft makes it traverse the river more slowly.

When FJ is on the raft alone, it can cross the river in M minutes (1 <= M <= 1000). When the i cows are added, it takes M_i minutes (1 <= M_i <= 1000) longer to cross the river than with i-1 cows (i.e., total M+M_1 minutes with one cow, M+M_1+M_2 with two, etc.). Determine the minimum time it takes for Farmer John to get all of the cows across the river (including time returning to get more cows).

Farmer John以及他的N(1 <= N <= 2,500)头奶牛打算过一条河,但他们所有的渡河工具,仅仅是一个木筏。 由于奶牛不会划船,在整个渡河过程中,FJ必须始终在木筏上。在这个基础上,木筏上的奶牛数目每增加1,FJ把木筏划到对岸就得花更多的时间。 当FJ一个人坐在木筏上,他把木筏划到对岸需要M(1 <= M <= 1000)分钟。当木筏搭载的奶牛数目从i-1增加到i时,FJ得多花M_i(1 <= M_i <= 1000)分钟才能把木筏划过河(也就是说,船上有1头奶牛时,FJ得花M+M_1分钟渡河;船上有2头奶牛时,时间就变成M+M_1+M_2分钟。后面的依此类推)。那么,FJ最少要花多少时间,才能把所有奶牛带到对岸呢?当然,这个时间得包括FJ一个人把木筏从对岸划回来接下一批的奶牛的时间。

输入输出格式

输入格式:
* Line 1: Two space-separated integers: N and M

  • Lines 2..N+1: Line i+1 contains a single integer: M_i

输出格式:
* Line 1: The minimum time it takes for Farmer John to get all of the cows across the river.

输入输出样例

输入样例#1:
5 10
3
4
6
100
1
输出样例#1:
50
说明

There are five cows. Farmer John takes 10 minutes to cross the river alone, 13 with one cow, 17 with two cows, 23 with three, 123 with four, and 124 with all five.

Farmer John can first cross with three cows (23 minutes), then return (10 minutes), and then cross with the last two (17 minutes). 23+10+17 = 50 minutes total.

分析:这题感觉很像背包,可以往背包靠。于是我们就设f【i】表示运i头牛到对面的最短时间,状态转移方程也就呼之欲出了:f【i】=max(f【i】,f【i-v】+w)。然后我们高高兴兴打了如下的代码:

for(i=1;i<=n;i++)
    {
        for(j=b[i];j<=n;j++)
        {
            f[j]=_min(f[j],f[j-b[i]]+a[i]);
        }
    }

一运行,发现不对啊!怎么回事,重新读题,哦,原来FJ回去的时间也要算!怎么处理呢?难不成要选完之后统计方案在输出吗?其实不必这样,我们可以把每次FJ回去的时间包含在里面(因为只要牛没运完,他就还要回去一次),在统计答案的时候减去一次FJ单独过河的时间就OK了(因为我们多算了一次,当FJ运最后一次的时候他是不会回去的)。代码如下:

#include<iostream>  
#include<cstring>  
#include<cmath> 
#include<algorithm> 
#include<cstdio> 
using namespace std;
long long a[2501],b[2501];
long long f[2501];
inline long long _read()//读入优化 
{
    long long x=0,flag=1;
    char s=getchar();
    while(s<'0'||s>'9')
    {
        if(s=='-')
        flag=-flag;
        s=getchar();
    }
    while(s>='0'&&s<='9')
    {
        x=x*10+s-48;
        s=getchar();
    }
    return x*flag;
}
inline long long _min(long long a,long long b)
{
    if(a<b) return a;
    return b;
}
int main()  
{  
    long long n=_read(),m=_read(),i,j;
    memset(f,0x7f,sizeof(f));//填满型背包,初始化无穷大 
    f[0]=0;//背包容量为0时合法 
    a[0]=m;
    for(i=1;i<=n;i++)
    {
        long long x=_read();//读入时间 
        a[i]=a[i-1]+x;//和上面的累加作为价值 
        b[i]=i;//这是物品体积 
    }
    for(i=1;i<=n;i++)
    {
        for(j=b[i];j<=n;j++)//完全背包 
        {
            f[j]=_min(f[j],f[j-b[i]]+a[i]+m);//算上每一次FJ回去的时间 
        }
    }
    printf("%lld",f[n]-m);//最后减去 
    return 0;  
}   

谢谢各位,有错误及时提出

posted @   最爱丁珰  阅读(28)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示