原谅我太菜第一次 接触状压dp,之前可能接触过没仔细学。。。
状压dp跟位运算有很大联系,位运算我也不太懂 我是真菜
下图是一些位运算的操作
状压dp是利用二进制来表达状态,将一个状态压缩为一个数,从而可以节省空间。
P1433 吃奶酪
房间里放着 nn 块奶酪。一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在 (0,0)(0,0) 点处。
用一个二进制数来记录走过的点,另一个数记录老鼠所在的点,如果之后搜到的答案比这个点要大,就不继续搜。搜完后最后判断结果
import java.util.Scanner;
public class Main{
static int n;
static double a[] = new double[205];
static double b[] = new double[205];
// static double ans=0x7fffffff;
static double anss;
static int flag[] = new int[50];
static double c[][] = new double[(1<<15)+15][50];//第一维记录走过的点,第二维记录所在的点
static double d[][] = new double[30][30];//记录状态
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
a[0]=0;b[0]=0;
for(int i=1;i<=n;i++){
a[i] = sc.nextDouble();
b[i] = sc.nextDouble();
for(int j=0;j<i;j++){
double xx = a[i] - a[j];
double yy = b[i] - b[j];
d[i][j] = Math.sqrt(xx*xx+yy*yy);
d[j][i] = d[i][j];
}
}
DFS(0,1,0,0);
System.out.println(String.format("%.2f", anss));
sc.close();
}
public static void DFS(int k,double num,int way,double ans){ //当前位置,搜过的点数量,搜过的点,距离
if(num==n+1){
if(anss==0||anss>ans){
anss = ans;
return;
}
}
for(int i=1;i<=n;i++){
if(flag[i]==1) continue;
int newway = way+(1<<(i-1));
if(c[newway][i]!=0){//剪枝
if(c[newway][i]<=d[k][i]+ans) continue;
}
c[newway][i] = ans+d[k][i];
flag[i]=1;
DFS(i,num+1,newway,c[newway][i]);
flag[i]=0;//回溯
}
}
}