题意:给你一些瓶子,有最小和最大装载容量,装载的容量必须在俩者之间,每个瓶子有无限多,对于一个L升的酒,用这些瓶子装的最大体积是多少。
输出剩余的酒量。
L<=1000000L
酒瓶
325ml <= max <= 4500ml
0.95max <= min <= 0.99max
解题思路:
考虑一个这样的瓶子,(min,max),假设在第K个的时候有(k+1)min < kmax(公式1)
这样,在kmin之后的数字就都可以组合出来。当 kmin <= x 时,剩余酒量一定是 0
由 公式1 有 min / (max-min) < k,俩边同时乘上 min
(min*min) / (max-min) < kmin <= x
取max = min / 0.99 (算x的最小值,左边要尽可能大,即分母要尽可能小,max-min最小)
所以根据题目条件可以算出,x最大是441045,也就是超过441045后的状态都不用算,一定可以装满。
#include <string> #include<iostream> #include <sstream> #include<map> #include<memory.h> #include<vector> #include<algorithm> #include<queue> #include<vector> #include<stack> #include<math.h> #include<iomanip> #include<bitset> #include"math.h" namespace cc { using std::cout; using std::endl; using std::cin; using std::map; using std::vector; using std::string; using std::sort; using std::priority_queue; using std::greater; using std::vector; using std::swap; using std::stack; using std::bitset; using std::stringstream; using std::abs; constexpr int BN = 110; constexpr int N = 441055; constexpr int MAXN = 4550; int s[BN]; int e[BN]; int vis[MAXN]; int nums[MAXN]; int dp[N]; void solve() { int n; int t = 0; cin >> n; while (n--) { if (t != 0) cout << endl; t++; int min = 0x7fffffff; int L, num; cin >> L >> num; L = 1000 * L; for (int i = 0; i < num; i++) { cin >> s[i] >> e[i]; if ((s[i] * s[i]) / (e[i] - s[i]) < min) { min = (s[i] * s[i]) / (e[i] - s[i]); } } if (L >= min) { cout << 0 << endl; } else { int k = 0; memset(vis,0,sizeof(vis)); for (int i=0;i<num;i++) { for (int j=s[i];j<=e[i];j++) { if (vis[j]==0) { vis[j] = 1; nums[k++] = j; } } } memset(dp,0,sizeof(dp)); for (int i=0;i<k;i++) { for (int j = nums[i];j<=L;j++) { if (dp[j-nums[i]] + nums[i] > dp[j]) { dp[j] = dp[j - nums[i]] + nums[i]; } } } cout << L - dp[L] << endl;; } } } }; int main() { #ifndef ONLINE_JUDGE freopen("d://1.text", "r", stdin); //freopen("d://1.out","w",stdout); #endif // !ONLINE_JUDGE cc::solve(); return 0; }