• 状压DP之吃奶酪


    题目

    传送们

    思路

    1≤n≤15,妥妥的状压,数据这么小,
    这道题的状压思路还是很好想的,我们定义f[i][s]代表以i为起点,吃掉状态为s的奶酪所需要跑的最短距离,那么显然,我们先枚举状态s,然后枚举出发点i,判断合法性(s是否包括i),然后枚举所需加入的起点j(s如果包含j则跳过),然后就可以很自然的推出转移方程

    f[i][s]=min(f[i][s],f[j][s-(1<<(i-1))]+dis(i,j));
    

    最后不要忘记加上出发点(0,0)就行了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1<<16;
    double f[20][maxn];
    double x[20],y[20];
    double dis(int i,int j){
    	double ans=0;
    	ans=sqrt((double)((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])));
    	return ans;
    }
    int main(){
    	int n;scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		cin>>x[i]>>y[i];
    	}
    	int lim=1<<n;
    	memset(f,0x7f,sizeof(f));
    	for(int i=1;i<=n;i++){
    		f[i][1<<(i-1)]=0;
    	}
    	for(int s=0;s<lim;s++){
    		for(int i=1;i<=n;i++){
    			if((s&(1<<(i-1)))==0)continue;
    			for(int j=1;j<=n;j++){
    				if(((s&(1<<(j-1)))==0)||i==j)continue;
    				f[i][s]=min(f[i][s],f[j][s-(1<<(i-1))]+dis(i,j));
    			}
    		}
    	}	
        double ans=-1;
        for(int i=1;i<=n;i++){
           double s=f[i][(1<<n)-1]+dis(i,0);
            if(ans==-1||ans>s) ans=s;
        }
        printf("%.2lf
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    NOIP 2012 T5 借教室 [洛谷P1083]
    POJ2437 Muddy roads
    POJ2288 Islands and Bridges
    洛谷P2014 TYVJ1051 选课
    POJ1741 Tree
    CODEVS1995 || TYVJ1863 黑魔法师之门
    TYVJ1939 玉蟾宫
    TYVJ1305 最大子序和
    POJ1737 Connected Graph
    TYVJ1864 守卫者的挑战
  • 原文地址:https://www.cnblogs.com/soda-ma/p/13236800.html
Copyright © 2020-2023  润新知