BZOJ 1617 [Usaco2008 Mar]River Crossing渡河问题:dp

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1617

题意:

  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一个人把木筏从对岸划回来接下一批的奶牛的时间。

 

题解:

  表示状态:

    dp[i] = min cost time

    i:已经运送了i只奶牛,并且FJ回到了河的这边。

 

  找出答案:

    ans = dp[n] - m

    最后一趟不用再回来,所以 - M。

 

  如何转移:

    dp[i+j] = min dp[i] + sum[j] + M

    枚举每一次运送j只牛,sum为一次性运送j只牛花费的时间。

    因为还要一个人回来,所以还要 + M。

 

  边界条件:

    dp[0] = 0

 

AC Code:

 1 // state expression:
 2 // dp[i] = min cost time
 3 // i: i cows have been transed
 4 //
 5 // find the answer:
 6 // ans = dp[n] - M
 7 //
 8 // transferring:
 9 // dp[i+j] = min dp[i] + sum[j] + M
10 //
11 // boundary:
12 // dp[0] = 0
13 #include <iostream>
14 #include <stdio.h>
15 #include <string.h>
16 #define MAX_N 2505
17 
18 using namespace std;
19 
20 int n,m;
21 int t[MAX_N];
22 int sum[MAX_N];
23 int dp[MAX_N];
24 
25 void read()
26 {
27     cin>>n>>m;
28     for(int i=1;i<=n;i++)
29     {
30         cin>>t[i];
31     }
32 }
33 
34 void solve()
35 {
36     sum[0]=2*m;
37     for(int i=1;i<=n;i++)
38     {
39         sum[i]=sum[i-1]+t[i];
40     }
41     memset(dp,0x3f,sizeof(dp));
42     dp[0]=0;
43     for(int i=0;i<n;i++)
44     {
45         for(int j=1;i+j<=n;j++)
46         {
47             dp[i+j]=min(dp[i+j],dp[i]+sum[j]);
48         }
49     }
50 }
51 
52 void print()
53 {
54     cout<<dp[n]-m<<endl;
55 }
56 
57 int main()
58 {
59     read();
60     solve();
61     print();
62 }

 

posted @ 2017-09-29 01:07  Leohh  阅读(176)  评论(0编辑  收藏  举报