[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\n",ans); return 0; }