Leedcode P1433 吃奶酪
题目描述
房间里放着 nn 块奶酪。一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在 (0,0)(0,0) 点处。
输入格式
第一行有一个整数,表示奶酪的数量 nn。
第 22 到第 (n + 1)(n+1) 行,每行两个实数,第 (i + 1)(i+1) 行的实数分别表示第 ii 块奶酪的横纵坐标 x_i, y_ixi,yi。
输出格式
输出一行一个实数,表示要跑的最少距离,保留 22 位小数。
输入输出样例
4 1 1 1 -1 -1 1 -1 -1
7.41
说明/提示
数据规模与约定
对于全部的测试点,保证 1\leq n\leq 151≤n≤15,|x_i|, |y_i| \leq 200∣xi∣,∣yi∣≤200,小数点后最多有 33 位数字。
提示
对于两个点 (x_1,y_1)(x1,y1),(x_2, y_2)(x2,y2),两点之间的距离公式为 \sqrt{(x_1-x_2)^2+(y_1-y_2)^2}(x1−x2)2+(y1−y2)2
#include<iostream> #include<cstring> #include<cmath> #include<iomanip> #define min(a,b) (((a)<(b))?(a):(b)) using namespace std; double a[16][16],F[16][34000]; double x[16],y[16]; int n; double dis(int v,int w){ return sqrt((x[v]-x[w])*(x[v]-x[w])+(y[v]-y[w])*(y[v]-y[w])); } int main(){ cin>>n; for(int i=1;i<=n;i++) cin>>x[i]>>y[i]; double ans; memset(F,127,sizeof(F)); ans=F[0][0]; x[0]=0; y[0]=0; for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) a[i][j]=dis(i,j);//记录所有距离,包括原点 for(int i=1;i<=n;i++) F[i][1<<(i-1)]=a[0][i];//所有到i点且只经过i点的F[][]均为i点到原点距离 for(int k=1;k<(1<<n);k++)//最后的结果是F[i][k],从j出发走到i点 { for(int i=1;i<=n;i++) { if(k&(1<<(i-1)==0))//F[][]还没有走过i continue; for(int j=1;j<=n;j++){ if(i==j)//不能自己走到自己 continue; if(k&(1<<(j-1)==0))//F[][]还没走过j continue; F[i][k]=min(F[i][k],F[j][k-(1<<(i-1))]+a[i][j]); } } } for(int i=1;i<=n;i++){ ans=min(ans,F[i][(1<<n)-1]); } cout<<fixed<<setprecision(2)<<ans<<endl; return 0; }
状压dp
这题dfs肯定超时。状压dp的时间复杂度为n*2^n。
状压就是用一个整数对应的二进制数来表示状态
那么首先要了解位运算
- ’&’符号,x&y,会将两个十进制数在二进制下进行与运算(都1为1,其余为0) 然后返回其十进制下的值。例如3(11)&2(10)=2(10)。
- ’|’符号,x|y,会将两个十进制数在二进制下进行或运算(都0为0,其余为1) 然后返回其十进制下的值。例如3(11)|2(10)=3(11)。
- ’^’符号,x^y,会将两个十进制数在二进制下进行异或运算(不同为1,其余 为0)然后返回其十进制下的值。例如3(11)^2(10)=1(01)。
- ’~’符号,~x,按位取反。例如~101=010。
- ’<<’符号,左移操作,x<<2,将x在二进制下的每一位向左移动两位,最右边用0填充,x<<2相当于让x乘以4。 ’>>’符号,是右移操作,x>>1相当于给x/2,去掉x二进制下的最右一位
1.判断一个数字x二进制下第i位是不是等于1。(最低第1位)
方法:if(((1<<(i−1))&x)>0) 将1左移i-1位,相当于制造了一个只有第i位 上是1,其他位上都是0的二进制数。然后与x做与运算,如果结果>0, 说明x第i位上是1,反之则是0。
2.将一个数字x二进制下第i位更改成1。
方法:x=x|(1<<(i−1)) 证明方法与1类似。
3.将一个数字x二进制下第i位更改成0。
方法:x=x&~(1<<(i−1))
4.把一个数字二进制下最靠右的第一个1去掉。
方法:x=x&(x−1)
第i个元素是否已经走过 i&(1<<(i-1))==0
所有元素全都走过,i&((1<<i)-1)==0
中间三层循环有点复杂。要清楚最里面表示的是什么状态。
有1组数据没过。

浙公网安备 33010602011771号