题解:P10884 [COCI 2017/2018 #2] San
dangerous_tDp · · 题解
较典的折半搜索。
看到
对于具体实现,有两种方式如下:
:::success[类 dfs]
参照此题解,拜谢巨佬作者。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 50;
int n, k, m, h[N], g[N], ans;
vector<int> pre[N];
signed main(){
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> k, m = n / 2;
for (int i = 1; i <= n; i ++)cin >> h[i] >> g[i];
for (int i = 1; i <= m; i ++){
for (int j = 0; j < i; j ++)
if (h[j] <= h[i])
for (auto v : pre[j])
pre[i].push_back(v + g[i]);
pre[i].push_back(g[i]);
}for (int i = n; i > m; i --){
for (int j = n + 1; j > i; j --)
if (h[j] >= h[i])
for (auto v : pre[j])
pre[i].push_back(v + g[i]);
pre[i].push_back(g[i]);
}for (int i = 1; i <= n; i ++)
sort(pre[i].begin(), pre[i].end());
for (int i = 1; i <= m; i ++)
ans += pre[i].size() - (lower_bound(pre[i].
begin(), pre[i].end(), k) - pre[i].begin());
for (int i = n; i > m; i --){
for (int j = 1; j <= m; j ++)
if (h[j] <= h[i])
for (auto v : pre[i])
ans += pre[j].size() - (lower_bound(pre[j].
begin(), pre[j].end(), k - v) - pre[j].begin());
ans += pre[i].size() - (lower_bound(pre[i].
begin(), pre[i].end(), k) - pre[i].begin());
}
return cout << ans, 0;
}
:::
:::success[类状压]
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 50;
int n, k, h[N], g[N], ans;
vector<int> pre[N];
signed main(){
ios::sync_with_stdio(0), cin.tie(0), cin >> n >> k;
for (int i = 1; i <= n; i ++)cin >> h[i] >> g[i];
int m = n / 2, l = n - m;h[n + 1] = 1e9;
for (int i = 0; i < (1 << m); i ++){
int nh = 0, s = 0, f = 0, lst = 0;
for (int j = 1; j <= m; j ++){
if ((1 << j - 1) & i)
if (h[j] >= nh)nh = h[j], s += g[j], lst = j;
else{f = 1;break;}
}
if (f)continue;pre[lst].push_back(s);
}for (int i = 1; i <= m; i ++)
sort(pre[i].begin(), pre[i].end()),
ans += pre[i].size() - (lower_bound(pre[i]
.begin(), pre[i].end(), k) - pre[i].begin());
for (int i = 0; i < (1 << l); i ++){
int nh = 0, s = 0, f = 0, fi = n + 1;
for (int j = 1; j <= l; j ++){
if ((1 << j - 1) & i)
if (h[j + m] >= nh)
nh = h[j + m], s += g[j + m],
fi = (fi == n + 1 ? j + m : fi);
else{f = 1;break;}
}if (f || fi == n + 1)continue;ans += s >= k;
for (int j = 1; j <= m; j ++)
if (h[j] <= h[fi])
ans += pre[j].size() - (lower_bound(pre[j].
begin(), pre[j].end(), k - s) - pre[j].begin());
}return cout << ans, 0;
}
:::
应该比较好理解,不懂私。