[codevs1243]网络提速

Posted Mrsrz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[codevs1243]网络提速相关的知识,希望对你有一定的参考价值。

题目大意:有n台电脑,m个加速器,每台电脑之间传输文件有一个时间,每个加速器可以使传输时间减半(两台电脑之间可以有多个加速器),求电脑1传输文件到电脑n的最短时间。

解题思路:有些人先求出最短路径,再每次找当前最短路径的最长边用加速器(即贪心),然而这种方法有反例。例如:

3 1

0 3 7

3 0 3

7 3 0

贪心的话求出来的是4.5(1-2-3,在1-2或2-3之间用加速器),然而最优解是3.5(1-3,在1-3之间用加速器)。

正确的解法应该是:最短路径+DP……吧(反正就是有点像最短路径又有点像DP的东西)。

直接上代码,在代码中有注释。

C++ Code:

 

#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
const double inf=1e30;//inf表示这两台计算机不能直接传输文件(t)/还没有解(dp)。
int n,m;
double t[51][51][11],dp[51][11];
//t[i][j][k]表示从第i台计算机到第j台用k台加速器的用时,dp[i][j]表示从第1台计算机到第i台用了j台加速器的最短用时。
typedef pair<int,int> pr;//第一个int保存当前的计算机编号,第二个int表示当前用了几台加速器。
queue<pr>q;
void work(){
	q.push((pr){1,0});
	while(!q.empty()){
		int num=q.front().first,jsq=q.front().second;
		q.pop();
		for(int i=1;i<=n;++i){
			if(fabs(t[num][i][0]-inf)>0.000001){
				for(int j=jsq;j<=m;++j){//枚举要使用的加速器台数 
					if(dp[i][j]>dp[num][jsq]+t[num][i][j-jsq]){//DP?SPFA? 
						dp[i][j]=dp[num][jsq]+t[num][i][j-jsq];
						q.push((pr){i,j});
					}
				}
			}
		}
	}
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
	for(int j=1;j<=n;++j){
		scanf("%lf",&t[i][j][0]);
		if(t[i][j][0]==0)t[i][j][0]=inf;else
		for(int k=1;k<=m;++k)t[i][j][k]=t[i][j][k-1]/2;//预处理
	}
	memset(dp,0,sizeof dp);
	for(int i=2;i<=n;++i)
	for(int j=0;j<=m;++j)dp[i][j]=inf;
	work();
	printf("%.2f\n",dp[n][m]);//因为用完m个加速器肯定比少用的优,所以答案是dp[n][m]。 
	return 0;
}

 

以上是关于[codevs1243]网络提速的主要内容,如果未能解决你的问题,请参考以下文章

[codevs1243]网络提速

网络提速(最短路)

16.网络提速(最短路)

IE7太慢,如何提速?

2019-07-05·家庭宽带提速换光猫EPON改GPON

codevs1922骑士共存问题——网络流