警钟敲得粉碎
查看原帖
警钟敲得粉碎
768144
_Trangle_楼主2024/7/12 15:19

DP 数组要全部初始化为 1

/**
 * 开始时间:2024-07-05 17:12:26
 * 预计完成时间:2024-07-05 17:30
 * 作者:zhizhi_c
 * 题目:P8816 [CSP-J 2022] 上升点列
 * 版本:0.0
 * 思路:考虑中间两点中间无任何点才能计算其用的自由点数量,跑一遍拓扑排序背包
 */
#include <bits/stdc++.h>
#define rep(i, b, e) for (auto i(b); i <= (e); i++)
#define req(i, b, e) for (auto i(b); i >= (e); i--)
#define range(i, b, e) for (auto i(b); i != (e); i++)
using namespace std;

const int N = 500, K = 100;
int n, k, ans;
int x[N+5], y[N+5], deg[N+5];
int dp[N+5][K+5];
vector<int> edge[N+5];
queue<int> q;

bool check(int p0, int p1) {
	rep(i, 1, n) {
		if ((i != p0 and i != p1) and
		    ((x[i] >= x[p0] and x[i] <= x[p1]) and (y[i] >= y[p0] and y[i] <= y[p1])))
			return false;
	}
	return true;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);
	cin >> n >> k;
	rep(i, 1, n) cin >> x[i] >> y[i];
	rep(i, 1, n) fill(dp[i], dp[i] + n+1, 1); //重点!!!

	range(i, 1, n) rep(j, i+1, n) {
		int p0 = make_pair(x[i], y[i]) < make_pair(x[j], y[j]) ? i : j, p1 = i ^ j ^ p0;
		if (y[p0] <= y[p1] and check(p0, p1)) {
			deg[p1]++;
			edge[p0].emplace_back(p1);
		}
	}
	rep(i, 1, n) {
		if (not deg[i]) q.emplace(i);
	}

	for (; not q.empty(); q.pop()) {
		int u = q.front();
		for (auto v: edge[u]) {
			int dis = x[v] + y[v] - x[u] - y[u];
			req(i, k, dis-1) dp[v][i] = max(dp[v][i], dp[u][i - dis + 1] + dis);
			if (not (--deg[v])) q.emplace(v);
		}
	}

	rep(i, 1, n) rep(j, 0, k) ans = max(ans, dp[i][j] + k - j);
	cout << ans;
	return 0;
}
2024/7/12 15:19
加载中...