[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]网络提速的主要内容,如果未能解决你的问题,请参考以下文章