intmain(){ int n; double M; scanf("%d%lf", &n, &M); printf("%f\n", M); vector<double> w(n, 0), p(n, 0); for (int i = 0; i < n; ++i) { scanf("%lf%lf", &w[i], &p[i]); } printf("%f\n", tmp); int ca = 0, cb = 0; for (int s = 0; s < (1<<(n/2)); ++s) { double tot_w = 0, tot_p = 0; for (int i = 0; i < n/2; ++i) { if (s&(1<<i)) { tot_w += w[i]; tot_p += p[i]; if (tot_w > M) break; } } if (tot_w <= M) { a[ca].w = tot_w; a[ca].p = tot_p; ca++; } } for (int s = 0; s < (1<<(n-n/2)); ++s) { double tot_w = 0, tot_p = 0; for (int i = 0; i < n-n/2; ++i) { if (s&(1<<i)) { tot_w += w[n/2+i]; tot_p += p[n/2+i]; if (tot_w > M) break; } } if (tot_w <= M) { b[cb].w = tot_w; b[cb].p = tot_p; cb++; } } sort(a, a+ca); sort(b, b+cb); vector<double> maxp(cb, 0); maxp[0] = b[0].p; for (int i = 1; i < cb; ++i) { maxp[i] = max(maxp[i-1], b[i].p); } int j = cb-1; double res = 0; for (int i = 0; i < ca; ++i) { while (j >= 0 && a[i].w+b[j].w > M) --j; if (j < 0) break; res = max(res, a[i].p+maxp[j]); } printf("%f\n", res); return0; }
最小长度子数组
给一个正数数组,找出最小长度连续子数组,其和大于等于 m。
题解
这题还是用双指针,首先用 i 遍历每一个位置,然后维护 a[j] ~ a[i] 之间的元素和。如果发现和大于等于 m ,那就更新最小长度,同时增大 j 直到区间和小于 m 。最终时间复杂度是 $O(n)$ 的。
代码
#include<bits/stdc++.h> usingnamespace std;
intmain(){ int n, m; scanf("%d%d", &n, &m); vector<int> a(n, 0); for (int i = 0; i < n; ++i) { scanf("%d", &a[i]); } int j = 0, sum = 0, res = INT_MAX; for (int i = 0; i < n; ++i) { sum += a[i]; while (sum >= m) { res = min(res, i-j+1); sum -= a[j++]; } } printf("%d\n", res); return0; }