zoukankan      html  css  js  c++  java
  • 洛谷P1171 售货员的难题 dp

    题目链接:https://www.luogu.com.cn/problem/P1171

    货郎担问题,经典的NPC难题,本题规模小,可用动态规划求解
    (dp[i][S]) 表示当前在城市 i,访问集合 S 中的城市各一次后回到城市 0 的最短长度,则

    [dp[i][S] = min{dp[j][S-{j}] + dis[j][i]},其中 j eq 0 ]

    注意两村庄之间的道路不一样长!!
    边界条件为(dp[i][0] = dis[0][i])
    答案即为 (dp[0][{1,2,3,...,n-1}])

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<stack>
    #include<queue>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 20;
    
    int n;
    int dis[maxn][maxn],dp[maxn][1<<maxn];
    
    ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }
    
    int main(){
    	memset(dp,0x3f,sizeof(dp)); 
    	n = read();
    	for(int i=0;i<n;i++){
    		for(int j=0;j<n;j++){
    			dis[i][j] = read();
    		}
    	}
    	
    //	for(int i=0;i<n;i++){
    //		for(int j=0;j<n;j++){
    //			printf("%d ",dis[i][j]);
    //		}printf("
    ");
    //	}
    	
    	for(int i=0;i<n;i++) dp[i][0] = dis[0][i];
    	
    	for(int s=1;s<(1<<(n));++s){
    		if(s&1) continue;
    		for(int i=0;i<n;++i){	
    			if(!(s & (1<<i))){
    				for(int j=1;j<n;++j){
    					if(s & (1<<j)){
    						dp[i][s] = min(dp[i][s],dp[j][s^(1<<j)] + dis[j][i]);
    					}
    				}
    //				printf("%d %d dp:%d
    ",i,ss,dp[i][ss]);
    			}
    		}
    	}
    	
    	int ans = 0;
    	
    	printf("%d
    ",dp[0][((1<<n)-1)^1]);
    	
    	return 0;
    }
  • 相关阅读:
    65_磁盘文件的使用
    64_设备文件的使用
    63_json解析成map格式
    62_json文件解析成结构体格式
    61_map生成json的使用
    60_通过结构体生成json
    59_字符串的转换
    58_字符串的一些操作函数的使用
    57_recover的使用
    56_异常处理error,errors和painc的使用
  • 原文地址:https://www.cnblogs.com/tuchen/p/13829388.html
Copyright © 2011-2022 走看看