【NOIP 2017】宝藏 D2 T2

参考From 传送门
写的很清晰了
AC code:

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 12;
const int MAXS = 4096;
const int INF = 0x3f3f3f3f;
int n, m, dis[MAXN][MAXN], ext[MAXS], dp[MAXS][MAXN];

inline bool chkmin(int &x, int y) { return y < x ? x = y, 1 : 0; }

int main ()
{
	int x, y, z;
	memset(dis, 0x3f, sizeof dis);
	scanf("%d%d", &n, &m);
	for(int i = 0; i < m; i++)
		scanf("%d%d%d", &x, &y, &z), dis[y-1][x-1] = dis[x-1][y-1] = min(dis[x-1][y-1], z);
	for(int i = 0; i < n; i++) dis[i][i] = 0;
	int all = (1<<n)-1;
	for(int i = 0; i <= all; i++)
		for(int j = 0; j < n; j++) if(i & (1<<j))
			for(int k = 0; k < n; k++)
				if(dis[j][k] != INF) ext[i] |= (1<<k);
	memset(dp, 0x3f, sizeof dp);
	for(int i = 0; i < n; i++) dp[1<<i][0] = 0;
	for(int s = 1; s <= all; s++)
		for(int s0 = (s-1)&s; s0; s0 = (s0-1)&s) if((ext[s0] | s) == ext[s0])
		{
			int ss = s^s0, sum = 0;
			for(int i = 0; i < n; i++) if(ss & (1<<i))
			{
				int tmp = INF;
				for(int j = 0; j < n; j++) if(s0 & (1<<j))
					chkmin(tmp, dis[j][i]);
				sum += tmp;	
			}		
			for(int i = 1; i < n; i++)
				chkmin(dp[s][i], dp[s0][i-1] + sum * i);
		}
	int Ans = INF;
	for(int i = 0; i < n; i++) chkmin(Ans, dp[all][i]);
	printf("%d
", Ans);
}
原文地址:https://www.cnblogs.com/Orz-IE/p/12039480.html