【区间DP】【DG特长生2017】T4摆渡线路

题目大意

有个圆,均匀分布 100 个点。编号从 1 到 100。
给你 n n n 组数对,一组数对 a , b a,b a,b 代表 a a a b b b 之间有一条连线。
你要保留尽可能多的连线,使得他们互不相交。


区间DP。
a n s [ i ] [ j ] ans[i][j] ans[i][j] i i i j j j 的弧间,最多可以保留的连线。
那么 a n s [ i ] [ j ] = m a x ( a n s [ i ] [ k ] + a n s [ k ] [ j ] ) + l [ i ] [ j ] ans[i][j] = max(ans[i][k]+ans[k][j]) + l[i][j] ans[i][j]=max(ans[i][k]+ans[k][j])+l[i][j]
( k k k 是 弧 i j ij ij 上的点, l l l i − j i-j ij 间是否有连线)
然后我处理了 i − j i-j ij 距离小于等于 50 50 50 的情况,再将两个半圆合并,得出最终结果。


代码

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
int n,a,b,l[120][120], e, le,ld, ans[120][120], anss;
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", &a, &b);
		l[a][b] = l[b][a] = 1;
	}
	for(int i = 2; i <= 51; ++i) //长度 
		for(int q = 1; q <= 100; ++q){
    
     //起始点 
			e = q+i-1; le = (e-1)%100+1;  //终点 
			for(int d = q; d <= e; ++d){
    
      //分割点
				ld = (d-1)%100+1;  //(这里前面带l的都是实际位置,不带的都是未经处理的
				ans[q][le] = ans[le][q] = max(ans[le][q], ans[q][ld]+ans[ld][le]); 
			}
			ans[q][le] += l[q][le];
			anss = max(anss, ans[q][le]);
		} 
	for(int i = 1; i <= 50; ++i)  //枚举是哪俩半圆最终合并
		anss = max(anss, 
		ans[i][i+49]+ans[i+50][(i+99-1)%100+1] //两半圆内连线数
		+l[i][(i+99-1)%100+1]+l[i+49][i+50] //两半圆之间连线
		+max(l[i][i+50], l[i+49][(i+99-1)%100+1])); //两半圆之间连线交叉的话取1
	printf("%d", anss);
	fclose(stdin);
	fclose(stdout);
} 

猜你喜欢

转载自blog.csdn.net/qq_42937087/article/details/115415413