POJ 1944 Fiber Communications , DP

http://poj.org/problem?id=1944

 

Fiber Communications

TimeLimit: 1000MS     MemoryLimit: 30000K

 

题目大意:

1~n个点依次排列,首尾相接,组成一个环。现在给出p对点,要求这中任意一对点之间要有线相连。

要求:一条线只能连接相邻的两个点。问至少要多少条线才能满足条件。

 

Sample Input

5 2

1 3

4 5

Sample Output

3

Hint

[Which connectbarn pairs 1-2, 2-3, and 4-5.] 

 

 

解法:

思路还是看了网上的题解。由于要求的是最少的线数,因此环中至少有一个断点。依次枚举每一个点作为一定存在的断点,然后对每种情况对进行讨论,再计算即可。

细节呈现在代码及注释中。其中to[]数组就是DP数组。

 

340K 125MS

/*
	从头断环为链,之后只讨论从左向右的连接。 
	由于整个连通环至少有一个断点,因此逐个枚举断点(并非唯一的断点,而是一定存在的断点), 
再计算这种情况下的连线数即可。 
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int inf=1010;

struct E{int st,ed;}e[inf*10];

int to[inf];//to[i]记录与第i个点连接的最右边的点
int n,p;
int ans=0x7fffffff;

int main(){
	cin>>n>>p;
	for (int i=1;i<=p;i++){
		scanf("%d%d",&e[i].st,&e[i].ed);
		if (e[i].st>e[i].ed) 
			swap(e[i].st,e[i].ed);
	}
	
	for (int i=1;i<=n;i++){		//枚举断点的位置
		
		memset(to,0,sizeof(to));
		
		for (int j=1;j<=p;j++){	//对每一对要求相连的点进行讨论
			int u=e[j].st,	v=e[j].ed;
			if (u<i && i<v) {	//断点在这对点中间,则连线要从链两头绕过(实质就是环)
				to[1]=max(to[1],u);
				to[v]=n+1;		//这样在计算边数时相当于从n~1有连线 
			} 
			else 				//断点不在这对点中间,则连线从这对点中间经过即可
				to[u]=max(to[u],v);
		}
		
		int sum=0,		//统计的边数 
			r=0;		//目前已连接的最右边的点
		for (int j=1;j<=n;j++){	//逐个点统计 
			if (!to[j])		//这个点没有向右连边
				continue;
			
			if (j>r){		//then	j连的边之前一定没有连过
				sum+=to[j]-j;
				r=to[j]; 
			} 
			else 			//j连的边之前可能被连过一部分 
			if (to[j]>r){	//j~r段已经连过,r~to[j]段还没有连
				sum+=to[j]-r;
				r=to[j]; 
			}
		} 
		ans=min(ans,sum);
	}	
	
	cout<<ans;
	return 0;
} 


©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值