zoukankan      html  css  js  c++  java
  • [NOIP2017]宝藏

    题目:洛谷P3959、UOJ#333、Vijos P2032。

    题意:
    给定一个有重边,边有权值的无向图。从某一个点出发,求到达所有的点需要的最少费用,
    并且限制两点之间只有一条路径。
    费用的计算公式为:所有边的费用之和。而边(x->y)的费用就为:y到初始点的距离 * 边权。
    解题思路:
    当时枚举边,拿了70分。
    正解状压dp,状压方式貌似很多。
    设(f_i)表示状态(i)下的最小费用,(dis_{ij})表示状态(i)最小费用下点(j)到出发点的总点数,(e_{ij})表示点(i)到(j)的最小边权。
    则(f_{i+2^j}=min(f_{i+2^j},f_i+dis_{ij} imes e_{jk})(jin i, k otin i))
    边界(f_{2^s}=0,dis_{2^s s}=1)
    当(f_i)更新时,(dis_i)需要整个更新。
    然后对于每个起点,答案为(f_{2^n-1}),其最小值就是答案。
    时间复杂度(O(2^n n^4))。

    C++ Code:

    #include<bits/stdc++.h>
    #define inf 0x3f3f3f3f
    int n,m,e[13][13],ans=inf,f[1<<14|1],dis[1<<14|1][13];
    inline int min(int a,int b){return a<b?a:b;}
    inline int readint(){
    	int c=getchar(),d=0;
    	for(;!isdigit(c);c=getchar());
    	for(;isdigit(c);c=getchar())
    	d=(d<<3)+(d<<1)+(c^'0');
    	return d;
    }
    int search(int s){
    	memset(f,0x3f,sizeof f);
    	f[1<<s]=0;
    	memset(dis,0,sizeof dis);
    	int N=1<<n;
    	dis[1<<s][s]=1;
    	for(int i=0;i<N;++i)
    	for(int j=0;j<n;++j)
    	if(i&(1<<j))
    	for(int k=0,p;k<n;++k)
    	if(!(i&(p=1<<k))&&(e[j][k]+1)){
    		int nw=f[i]+dis[i][j]*e[j][k];
    		if(nw<f[i|p]){
    			f[i|p]=nw;
    			memcpy(dis[i|p],dis[i],sizeof dis[i]);
    			dis[i|p][k]=dis[i][j]+1;
    		}
    	}
    	return f[N-1];
    }
    int main(){
    	n=readint(),m=readint();
    	memset(e,-1,sizeof e);
    	for(int i=1;i<=m;++i){
    		int u=readint()-1,v=readint()-1,t=readint();
    		if(e[u][v]==-1||e[u][v]>t)e[u][v]=e[v][u]=t;
    	}
    	for(int i=0;i<n;++i)ans=min(ans,search(i));
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    sudo详解
    Linux按照CPU、内存、磁盘IO、网络性能监测
    基于kickstart定制自动化安装的linux镜像系统
    基于busybox和LFS的linux系统定制
    syslog及syslog-ng详解 日志服务器
    yum报错
    二进制程序及其依赖库的移植脚本
    Linux 系统裁剪
    linux 内核手动编译
    linux rc.sysinit文件详解
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9118623.html
Copyright © 2011-2022 走看看