[NOIP2017]宝藏

解题思路:听说状压dp有后效性,然后被Hack了。
于是用随机化大法,每次random_shuffle一个加入点的顺序,然后贪心地插入点。如此多算几次就能找到最优解(我不会证明它为什么可能找到最优解)。

C++ Code:

#include<bits/stdc++.h>
int n,m,e[13][13],p[13],d[13];
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 main(){
	memset(e,0x3f,sizeof e);
	n=readint(),m=readint();
	for(int i=1;i<=n;++i)p[i]=i;
	while(m--){
		int x=readint(),y=readint(),t=readint();
		if(e[x][y]>t)e[x][y]=e[y][x]=t;
	}
	int ans=0x3f3f3f3f;
	for(int T=1,sm;T<=100000;++T){
		std::random_shuffle(p+1,p+n+1);
		memset(d,0,sizeof d);
		sm=0;
		d[p[1]]=1;
		for(int i=2;i<=n;++i){
			int s=0x3f3f3f3f;
			for(int j=1;j<i;++j)
			if(e[p[i]][p[j]]<0x3f3f3f3f&&d[p[j]]*e[p[i]][p[j]]<s){
				s=d[p[j]]*e[p[i]][p[j]],d[p[i]]=d[p[j]]+1;
			}
			if(s==0x3f3f3f3f){
				sm=s;break;
			}else sm+=s;
		}
		if(sm<ans)ans=sm;
	}
	printf("%d
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/Mrsrz/p/9164196.html