LG 3959 宝藏
状压DP
蒟蒻想了个\(O(N^3\ast 3^N)\)的
膜拜SZR博客之后
才知道怎么优化掉一个N
码力同翔
1.5h才过样例
#include <iostream>
#include <cassert>
using namespace std;
const long long LONF=4567891012345678910LL;
const int INF=1034567890;
const int MAXN=13;
const int MAXM=4111;
int N, M;
long long Map[MAXN][MAXN];
long long F[MAXN][MAXN][MAXM];
int Cnt[MAXM];
int Mat[MAXN][MAXN][MAXM];
long long MinC, Cost;
long long lmin(long long a, long long b){
return (a>b)?b:a;
}
int main(){
ios_base::sync_with_stdio(false);
cin >> N >> M;
for(int i=0;i<N;++i)
for(int j=0;j<N;++j)
Map[i][j]=(long long)(INF);
for(int i=0;i<N;++i) Map[i][i]=0LL;
for(int i=1, a, b, v;i<=M;++i){
cin >> a >> b >> v;--a;--b;
Map[a][b]=lmin(Map[a][b], (long long)(v));
Map[b][a]=lmin(Map[b][a], (long long)(v));
}
M=(1<<N);
for(int i=0;i<=N;++i)
for(int j=0;j<=N;++j)
for(int p=0;p<M;++p)
F[i][j][p]=LONF, Mat[i][j][p]=-1;
for(int i=0, k;i<M;++i){
k=i;Cnt[i]=0;
while(k>0){
if(k&1) ++Cnt[i];
k>>=1;
}
}
for(int s=1, i=0;s<M;s<<=1, ++i){
for(int j=0;j<N;++j){
F[i][j][s]=0LL;
}
for(int j=0;j<N;++j){
if(j==i) continue;
for(int d=0;d<N;++d){
Mat[j][d][s]=i;
}
}
}
for(int s=1;s<M;++s){
if(Cnt[s]<=1) continue;
for(int ss=(s-1)&s, iss;ss>0;ss=(ss-1)&s){
iss=s-ss;
for(int d=0;d+Cnt[s]<=N;++d){
for(int i=0, j;i<N;++i){
if(((1<<i)&ss)==0) continue;
j=Mat[i][d][iss];
//cout << i << " " << d << " " << iss << endl;
assert(j>-1 && j<N);
//cout << "(" << i << "," << d << "," << s << ")<-(" << j << "," << d+1 << "," << iss << ")" << endl;
F[i][d][s]=lmin(F[i][d][s], F[i][d][ss]+Map[i][j]*(long long)(d+1)+F[j][d+1][iss]);
}
}
}
for(int i=0;i<N;++i){
if(((1<<i)&s)!=0) continue;
for(int d=0;d+Cnt[s]<=N;++d){
Mat[i][d][s]=-1;MinC=LONF;
for(int j=0;j<N;++j){
if(((1<<j)&s)==0) continue;
Cost=F[j][d+1][s]+Map[i][j]*(long long)(d+1);
if(Cost<MinC){
MinC=Cost;Mat[i][d][s]=j;
}
}
}
}
}
/*
for(int s=1;s<M;++s){
for(int i=0;i<N;++i){
if(((1<<i)&s)==0) continue;
for(int d=0;d+Cnt[s]<=N;++d){
cout << i << " " << d << " " << s << " " << F[i][d][s] << endl;
}
}
}
*/
long long ANS=LONF;
for(int i=0;i<N;++i)
ANS=lmin(ANS, F[i][0][M-1]);
cout << ANS << endl;
return 0;
}