Problem A: 无奈的学长
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 26 Solved: 3
[ Submit][ Status][ Web Board]
Description
众所周知,YONG学长是一个有妹子的汉子,可是众所不周知,有妹子的汉子给学弟出一道题做也会经常被打断。
“喂,亲爱的,我在A区,你在学院给我采几朵花,然后拿给我看好吗?”
“可是...我在宿舍...给学弟们出题...”
“立马的...”
“...”
“我有一个要求,采花的时候,每次经过一条路,只能在这条路上采一朵最好的给我。要快哦~”
“...”
逆来顺受&悲愤交加的YONG学长,为了能挤出更多时间出题,只好手工计算出一条距离最短的路径。
还好计算过程只花了短短半个小时,后来他兴高采烈的去见了学姐,卒。
假若时光能够倒流,聪明善良的你是否愿意帮助YONG学长找到这个距离最短的路径,输出路径长度。
hint:
任意两个建筑物之间都是一条路。
假设每条路上有无数多花。
假设YONG学长每次都能在走完一条路后找到最好的花并采下。
题目保证数据合理。
...
不要在意这些细节。
Input
多case。
每个case第一行输入一个数字N(1 <= N <= 30),代表学院一共有多少个地点(地点从1到N标号)。
下面N行,每行两个数字x,y,(0 < x < 30,0 < y < 30)代表该地点的物理坐标。
最后一行两个三数字,S和E,K(1 <= K <= 10000000)分别代表YONG学长和学姐在电话刚刚打通时候的地点标号,以及学姐要得到的花数目。
Output
每个输出独占一行,结果保留小数点后两位。
Sample Input
10 01 1 020 00 11 1 2
Sample Output
0.002.00
HINT
floyd算法的方程是f[i,j] = min(f[i,k]+f[k,j])k∈[1,n]
将矩阵乘法的算法c[i,j] = ∑(a[i,k]*b[k,j])稍微修改一下就得到任意i,j间经过一次转移的最短路。
由于不能在原地停留,所以原矩阵的主对角线为正无穷。
矩阵乘法用快速幂实现。
时间复杂度为O(n^3lgK)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 40;
/
int n;
struct matrix
{
double m[maxn][maxn];
void operator*=(matrix m2)
{
matrix rs;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
rs.m[i][j] = 1e18;
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
{
for (int k=1;k<=n;k++)
{
rs.m[i][j] = min(rs.m[i][j],m[i][k]+m2.m[k][j]);
}
}
}
*this = rs;
//return rs;
}
void clear(){memset(m,0,sizeof m);for(int i=1;i<=n;i++)m[i][i]=1e18;}
matrix(){clear();}
matrix(const matrix& m2)
{
clear();
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
m[i][j] = m2.m[i][j];
}
void operator=(const matrix& m2)
{
clear();
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
m[i][j] = m2.m[i][j];
}
};
//matrix a;
matrix map;
/
matrix kp(int k)
{
matrix ans = map;
matrix tmp = map;
while (k)
{
if (k&1){ans*=tmp;}
tmp *= tmp;
k >>= 1;
}
return ans;
}
int x[maxn];
int y[maxn];
int main()
{
while (scanf("%d",&n) != EOF)
{
for (int i=1;i<=n;i++)
scanf("%d%d",x+i,y+i);
map.clear();
for (int i=1;i<=n;i++)
{
for (int j=i+1;j<=n;j++)
{
map.m[i][j] = map.m[j][i] = sqrt(double(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
}
int s,e,k;
scanf("%d%d%d",&s,&e,&k);
if (n == 1)
{
printf("0.00\n");
continue;
}
if (k <= 1)
{
printf("%.2f\n",map.m[s][e]);
continue;
}
matrix ans = kp(k-1);
printf("%.2f\n",ans.m[s][e]);
}
return 0;
}
/**************************************************************
Problem: 1259
User: wuyihao
Language: C++
Result: Accepted
Time:3 ms
Memory:1084 kb
****************************************************************/