题解:AT_arc104_c [ARC104C] Fair Elevator
[ARC104C] Fair Elevator
https://www.luogu.com.cn/problem/AT_arc104_c
感觉很好想也很好写的 DP 做法,实现方法不太一样。
先把无解的判掉,定义
借个图,如果一个区间能够合法,其一定如下图所示:
那么对于一个区间我们判断它要用多少个
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a), stOwxc = (b); i <= stOwxc; i++)
#define per(i, a, b) for(int i = (a), stOwxc = (b); i >= stOwxc; i--)
using namespace std;
using LL = long long;
using VI = vector<int>;
constexpr int INF = 1e9;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int n; cin >> n;
set<pair<int, int>> s;
int cnt = 0;
for(int i = 1, x, y; i <= n; i++) {
cin >> x >> y;
if(x > y && x != -1 && y != -1) return cout << "No" << '\n', 0;
if(x == -1 && y == -1) {
cnt++;
continue;
}
if(s.count({x, y})) return cout << "No" << '\n', 0;
s.insert({x, y});
}
auto check = [&](int r, int j) {
int l = r - (j + 1) * 2 + 1;
int ret = 0;
rep(i, l, r - (j + 1))
if(!s.count({-1, i + j + 1}) && !s.count({i, -1}) && !s.count({i, i + j + 1})) ret++;
return ret;
};
vector<int> F(n * 2 + 1, INF);
F[0] = 0;
rep(i, 1, 2 * n) rep(j, 0, i) {
if(i - (j + 1) * 2 < 0) break;
F[i] = min(F[i], F[i - (j + 1) * 2] + check(i, j));
}
cout << (F[2 * n] <= cnt ? "Yes" : "No") << '\n';
return 0;
}