NOIp2017D2T2(luogu3959) 宝藏 (状压dp)

时隔多年终于把这道题过了

数据范围显然用搜索剪枝状压dp。

可以记还有哪些点没到(或者已到了哪些点)、我们最深已到的是哪些点、这些点的深度是多少,然后一层一层地往下推。

但其实是没必要记最深的那一层的,只要强行装作每次更新都是用最深的深度更新就可以。这样的话,虽然会有很多情况偏大,但是能正确更新的情况其实是都已经包括了。

因为你如果想以当前状态去更新,但用的还不是最深一层的点的话,干脆就可以在之前你想用那个点处于最后一层的时候去更新。

代码写的很捉急..最后常数也很捉急...

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<queue>
 6 #include<cmath>
 7 #include<ctime>
 8 #define LL long long int
 9 #define inf 0x3f3f3f3f
10 using namespace std;
11 const int maxs=5000,maxn=15,maxm=1010;
12 
13 LL rd(){
14    LL x=0;char c=getchar();int neg=1;
15    while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
16    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
17    return x*neg;
18 }
19 
20 int eg[maxm*2][3],egh[maxn],ect;
21 int f[maxn][maxs],dis0[maxs][maxn],dis[maxs][maxs],bin[maxn];
22 int N,M;
23 
24 inline void adeg(int a,int b,int v){
25     eg[ect][0]=b;eg[ect][1]=egh[a];eg[ect][2]=v;egh[a]=ect++;
26     for(int i=1;i<bin[N+1];i++) if((bin[a]&i) && !(bin[b]&i)) dis0[i][b]=min(dis0[i][b],v);
27 }
28 
29 void dfs(int x,int y,int s,int e){
30     if(x>N) dis[s][e]=y;
31     else{
32         if(dis0[s][x]<=500000) dfs(x+1,y+dis0[s][x],s,e|bin[x]);
33         dfs(x+1,y,s,e);
34     }
35 }
36 
37 int main(){
38     int i,j,k;
39     N=rd(),M=rd();
40     memset(egh,-1,sizeof(egh));memset(dis,127,sizeof(dis));
41     memset(dis0,127,sizeof(dis0));memset(f,127,sizeof(f));
42     for(i=1,j=1;i<=N+1;i++,j<<=1) bin[i]=j;
43     for(i=1;i<=M;i++){
44         int a=rd(),b=rd(),c=rd();
45         adeg(a,b,c);adeg(b,a,c);
46     }
47     for(i=1;i<bin[N+1];i++) dfs(1,0,i,0);
48     for(i=1;i<=N;i++) f[1][bin[i]]=0;
49     for(i=1;i<N;i++){
50         for(j=1;j<bin[N+1];j++){
51             if(f[i][j]>=9e7) continue;
52             for(k=1;k<bin[N+1];k++){
53                 if(dis[j][k]>500000) continue;
54                 f[i+1][j|k]=min(f[i+1][j|k],f[i][j]+i*dis[j][k]);
55             }
56         }
57     }int ans=0x3f3f3f3f;
58     for(i=1;i<=N;i++) ans=min(f[i][(1<<N)-1],ans);
59     printf("%d\n",ans);
60     return 0;
61 }

猜你喜欢

转载自www.cnblogs.com/Ressed/p/9588395.html