HNU 12961 BitTorrent DP

題意:ios

  你在網上下載東西,一個文件存儲在一段或者多段裏面,問怎麼選擇能在規定的流量內下載最多的文件數量。每段的大小同樣。數組

思路:ide

  習慣了作答案保存在DP數組裏的題,作這種答案保存在下標裏的題,轉不過彎來。開始想過揹包,可是一來內存不夠,二來時間也不夠。spa

  實際上是這樣作的,dp[i][j][0/1]保存枚舉到第i個,下載了j個,最後一個是否被下載的最小花費。 最後找花費沒超過限制的最大值就行了。3d

  最後值得注意的是,最後一段的時候,可能不會被p整除,不要算多了哦。code

 

代碼:blog

  

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <cmath>
 6 #include <algorithm>
 7 #include <string>
 8 #include <queue>
 9 #include <stack>
10 #include <vector>
11 #include <map>
12 #include <set>
13 #include <functional>
14 #include <cctype>
15 #include <time.h>
16 
17 using namespace std;
18 
19 const int INF = 1<<30;
20 const int MAXN = 3055;
21 
22 int dp[MAXN][MAXN][2]; //dp[i][j][k] 表示取到第i個,取了j個,的時候,第i個取或者不取
23 int a[MAXN];
24 int sum[MAXN]; //前綴和
25 int n, p, l;
26 
27 int main() {
28     #ifdef Phantom01
29         freopen("HNU12961.in", "r", stdin);
30     #endif //Phantom01
31 
32     while (scanf("%d%d%d", &n, &p, &l)!=EOF) {
33         if (n==0&&p==0&&l==0) break;
34 
35         sum[0] = 0;
36         for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
37         for (int i = 1; i <= n; i++) sum[i] = sum[i-1]+a[i];
38         for (int i = 0; i <= n; i++)
39             for (int j = 0; j <= n; j++)
40                 dp[i][j][0] = dp[i][j][1] = INF;
41         dp[0][0][0] = 0;
42 
43         for (int i = 1; i <= n; i++) {
44             for (int j= 0; j <= i; j++)
45                 dp[i][j][0] = min(dp[i-1][j][0], dp[i-1][j][1]);
46             for (int j = 1; j <= i; j++)
47                 dp[i][j][1] = min(dp[i-1][j-1][0]-(sum[i-1]/p)*p,
48                                   dp[i-1][j-1][1]-((sum[i-1]+p-1)/p)*p)
49                               + (i==n ? sum[i] : ((sum[i]+p-1)/p)*p);
50         }
51         int ans = 0;
52         for (int i = 0; i <= n; i++)
53             if (dp[n][i][0]<=l || dp[n][i][1]<=l)
54                 ans = max(ans, i);
55         printf("%d\n", ans);
56     }
57 
58     return 0;
59 }
View Code
相關文章
相關標籤/搜索