【DG特长生2017 T4】【SSL 2877】【SSL 1964】【SSL 1599】摆渡线路

本文介绍了一种算法,如何在均匀分布的100个圆点中,通过动态规划求解最多能保留的不相交线段。通过区间划分和dp计算,确定每条线段的选择,最后输出最大可选线段数。

摆渡线路

题目链接:SSL 2877 / SSL 1964 / SSL 1599

题目大意

有一个圆,均匀分布 100 个点从 1 到 100。
然后两个点之间可能会有线段。
然后要你保留尽可能多的线段,使得保留的线段互不相交。

思路

这道题看到环,先把它弄成链。

然后你就会发现其实就是要你选的线段在链上不会有重叠而且不是全部重叠的部分。
那你可以考虑用 dp 来解决。

就枚举中间中转的地方,把一个大的区间分成两个小的区间。
然后如果你大区间左右端点间有线,那这条线是一定可以选的。

那你可以用这样的方法,设 f i , j f_{i,j} fi,j i i i j j j 最多可以选多少条线。
f i , j = max ⁡ i ≤ k ≤ j { f i , k + f k , j } + a i , j f_{i,j}=\max\limits_{i\leq k \leq j}\{f_{i,k}+f_{k,j}\}+a_{i,j} fi,j=ikjmax{fi,k+fk,j}+ai,j
a i , j a_{i,j} ai,j 是两点间是否有线段。

然后你最后找到 f i , i + 100 f_{i,i+100} fi,i+100 中最大的那个输出即可。

代码

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

int n, x, y, f[201][201], ans, a[201][201];

int main() {
//	freopen("line.in", "r", stdin);
//	freopen("line.out", "w", stdout);
	
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d %d", &x, &y);
		if (x > y) swap(x, y);
		a[x][y] = 1;
		a[x + 100][y + 100] = 1;//把环弄成链
	}
	
	for (int dis = 1; dis <= 100; dis++)//区间dp
		for (int i = 1; i + dis - 1 <= 200; i++) {
			int j = i + dis - 1;
			for (int k = i; k <= j; k++)
				f[i][j] = max(f[i][j], f[i][k] + f[k][j]);
			f[i][j] += a[i][j];
		}
	
	for (int i = 1; i <= 100; i++)
		ans = max(ans, f[i][i + 100 - 1]);
	
	printf("%d", ans);
	
	fclose(stdin);
	fclose(stdout);
	
	return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值