• [NOIP2017 TG D2T2]宝藏


    题目大意:给定一个有重边,边有权值的无向图。从某一个点出发,求到达所有的点需要的最少费用,并且限制两点之间只有一条路径。费用的计算公式为:所有边的费用之和。而边$x->y$的费用就为:$y$到初始点的之间点的个数(包括起始点) $ imes$ 边权。

    题解:状压$DP$,令$f_{i,j}$表示当前深度为$i$,状态为$j$的最小花费

    $$f_{i,s}=f_{i-1,t}+g_{s,t} imes(i−1)$$

    再开一个数组$c_{s,i}表示状态$s$挖到点$i$的最小花费(不考虑深度)

    用边权更新$c$数组,再用$c$数组更新$g$数组即可

    卡点:1.$c$数组第二维开太小

    C++ Code:

    #include <cstdio>
    #include <cstring>
    #define lb(x) (x & -x)
    #define maxn 13
    using namespace std;
    const int inf = 0x3f3f3f3f;
    int n, m, U, ans = inf; 
    int e[maxn][maxn], c[maxn][1 << maxn | 3];
    int g[1 << maxn | 3][1 << maxn | 3], f[maxn][1 << maxn | 3];
    inline void getmin(int &a, int b) {if (a > b) a = b;}
    inline int min(int a, int b) {return a < b ? a : b;}
    int main() {
    	scanf("%d%d", &n, &m); U = 1 << n;
    	if (n == 1) {
    		puts("0");
    		return 0;
    	}
    	memset(e, 0x3f, sizeof e);
    	for (int i = 0; i < m; i++) {
    		int a, b, c;
    		scanf("%d%d%d", &a, &b, &c);
    		e[a][b] = e[b][a] = min(c, e[a][b]);
    	}
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j < U; j++) {
    			c[i][j] = inf;
    			if (!(j & (1 << i - 1))) {
    				for (int k = 1; k <= n; k++) {
    					if (j & (1 << k - 1)) getmin(c[i][j], e[i][k]);
    				}
    			}
    		}
    	}
    	for (int i = 1; i < U; i++) {
    		for (int j = i & i - 1; j; j = i & j - 1) {
    			int tmp = i ^ j;
    			for (int k = 1; k <= n; k++) {
    				if (tmp & (1 << k - 1)) {
    					g[i][j] += c[k][j];
    					if (g[i][j] > inf) g[i][j] = inf;
    				}
    			}
    		}
    	}
    	memset(f, 0x3f, sizeof f);
    	for (int i = 1; i <= n; i++) f[1][1 << i - 1] = 0;
    	for (int i = 2; i <= n; i++) {
    		for (int j = 1; j < U; j++) {
    			for (int k = j & j - 1; k; k = j & k - 1) {
    				int tmp = inf;
    				if (g[j][k] ^ inf) tmp = g[j][k] * (i - 1);
    				if (f[i - 1][k] ^ inf) getmin(f[i][j], f[i - 1][k] + tmp);
    			}
    		}
    		getmin(ans, f[i][U - 1]);
    	}
    	printf("%d
    ", ans);
    	return 0;
    } 
    

      

  • 相关阅读:
    170110-学习MoveIt!
    12.29-ros-gazebo高级
    12.27-ros-gazebo基础
    4.9-Simulation in gazebo or webots
    6.28-机器人模拟器Gazebo基础
    4.8-URDF in ROS
    Win32双缓冲画图原理
    Win32 计时器
    最简化的DirectX 11开发环境的配置 VS2010
    VS2010 C++编译报错LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/9504801.html
Copyright © 2020-2023  润新知