hiho1270 建造基地([Offer收割]编程练习赛1)

题目意思很简单,

一道类似于背包的问题,问恰好超过背包容量的最小取值。并且需要计算n次,每计算一次都要将所有的物品的价值w[i] /= t,最后输出背包n次的总使用容量。

如果无法实现输出”No Answer”。

就是背包的变形,或者用队友的话说,当做dp做就好了,管它是不是背包呢。

主要就是状态转移方程了,其它没什么难点。

……感觉自己好水。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 #define LL long long
 8 
 9 const LL L = 1e17;
10 const int W = 10010;
11 
12 int t_t;
13 int n, m, k, t;
14 LL a[W], b[W], dp[W];
15 LL ans;
16 bool flag;
17 
18 LL Min(LL x, LL y)
19 {
20     return (x == -1 || x > y) ? y : x;
21 }
22 
23 int main()
24 {
25     //freopen("test.in", "r", stdin);
26     scanf("%d", &t_t);
27     for(int tm = 1; tm <= t_t; tm++)
28     {
29         scanf("%d%d%d%d", &n, &m, &k, &t);
30         for(int i = 0; i < m; i++) cin >> a[i];
31         for(int i = 0; i < m; i++) cin >> b[i];
32 
33         ans = 0;
34         for(int ii = 1; ii <= n; ii++)
35         {
36             memset(dp, -1, sizeof(dp));
37             dp[0] = 0;
38             flag = 0;
39             for(int i = 0; i < m; i++)
40             {
41                 if(b[i] == 0) continue;
42                 for(int j = 0; j <= k; j++)
43                 {
44                     int mid = j-b[i]>0 ? j-b[i] : 0;
45                     //;
46                     dp[j] = Min(dp[j], dp[mid]+a[i]);
47                     //cout << b[i] << "#############" << dp[j] << endl;
48                 }
49             }
50             //cout << "............................" << dp[k] << endl;
51             if(dp[k] == -1) {flag = 1; break;}
52             ans += dp[k];
53             for(int i = 0; i < m; i++) b[i] /= t;
54         }
55         if(flag) cout << "No Answer" << endl;
56         else cout << ans << endl;
57 
58     }
59 }
View Code
原文地址:https://www.cnblogs.com/mypride/p/5269099.html