题目描述
房间里放着n块奶酪。一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在(0,0)点处。
输入输出格式
输入格式:
第一行一个数n (n<=15)
接下来每行2个实数,表示第i块奶酪的坐标。
两点之间的距离公式=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
输出格式:
一个数,表示要跑的最少距离,保留2位小数。
输入输出样例
输入样例#1
4
1 1
1 -1
-1 1
-1 -1
输出样例#1
7.41
思路
这题需要bfs?一个dfs+剪枝就解决了。(其实就是我太弱了)
好啦,普及一下姿♂势,那就是如何用cout输出小数点后指定位数,因为题目要求保留2位小数。
setprecision()函数,作用是保留有效n位有效数字。如,对于一个浮点数1.414,如果setprecision(2),就会输出1.41。
还有一个问题,如果输入1.400001,保留2位小数,会输出1.4,后面的0会被省略。
如果我们想要让它自动补0,需要在cout之前进行补0的定义,需要用fixed。
还有,上面这些东西都要加上头文件iomanip。
cout<<fixed<<setprecision(2)<<1.400004<<endl;//输出1.40
言归正传
直接dfs肯定超时,因此要剪枝。
已经吃掉的奶酪要记录,尝试走过的路径要归位。
#include <stdio.h>
#include <math.h>
#include <iomanip>//一定要加上!
#include <iostream>
using namespace std;
double a[1001],b[1001],len[1001][1001],minx(0x7fffff);
int n;
bool check[1001];
inline void dfs(double minn,int now,int b)//b走完多少个坐标点,now当前坐标点,minn为走到的路径长
{
register int i,j;
if(minn>minx)//剪枝,如果当前路径比当前最短的长,不必继续搜了
{
return;
}
if(b==n)//走完了
{
minx=fmin(minx,minn);//更新最短路径
return;
}
for(i=1;i<=n;i++)//尝试每一种点
{
if(check[i]==0)//如果这个点没有走过
{
check[i]=1;//走过了
minn=minn+len[now][i];//当前方案路径加上这步要走的路径
dfs(minn,i,b+1);//尝试下一步,b+1为下一步,i为控制变量,可以当当前坐标点使用
check[i]=0;//走过的路要退回
minn=minn-len[now][i];//坐标点也要直到为0
}
}
return;
}
int main()
{
ios::sync_with_stdio(false);
cout.setf(ios::fixed);
register int i,j;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>a[i]>>b[i];//输入坐标点
}
for(i=0;i<=n;i++)
{
for(j=0;j<=n;j++)
{
len[i][j]=sqrt((a[i]-a[j])*(a[i]-a[j])+(b[i]-b[j])*(b[i]-b[j]));//计算坐标点之间的距离
//cout<<len[i][j]<<' ';
}
//cout<<endl;
}
dfs(0.0,0,0);//全tm从0开始,从0层开始搜
if(minx==0x7fffff)//这个值都没动过,一个路径也没有
cout<<-1<<endl;
else
cout<<fixed<<setprecision(2)<<minx<<endl;//输出最短路径
cout.unsetf(ios::fixed);
return 0;
}