生活随笔
收集整理的這篇文章主要介紹了
洛谷P2761:软件补丁问题(状压、分层图最短路)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
當遇到瓶頸時,想想自己是否做了可以優化的無用功。
解析
不難想到狀壓最短路的做法。
但是直接加邊的話邊數會是 O(m2n)O(m2^n)O(m2n) 級別,只有 909090 分,難以通過。
注意到,由于補丁很少,真正能達到的狀態是很有限的。所以我們不真正加邊,而是在每次枚舉出邊時改為遍歷所有補丁利用合法的補丁轉移即可。
#include<bits/stdc++.h>
using namespace std
;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
inline ll
read(){ll
x(0),f(1);char c
=getchar();while(!isdigit(c
)){if(c
=='-') f
=-1;c
=getchar();}while(isdigit(c
)){x
=(x
<<1)+(x
<<3)+c
-'0';c
=getchar();}return x
*f
;
}
const int N
=2e6+100;
const int M
=1e6+100;
const int inf
=1e9;int n
,m
;int mi
[30],S
;
char s1
[30],s2
[30];
int dis
[N
];
#define mkp make_pair
#define pr pair<int,int>
priority_queue
<pr
,vector
<pr
>,greater
<pr
> >q
;
bool vis
[N
];
int ned
[105],no
[105],add
[105],del
[105],val
[105];
void dij(){memset(dis
,0x3f,sizeof(dis
));dis
[S
]=0;q
.push(mkp(0,S
));while(!q
.empty()){int now
=q
.top().second
;q
.pop();if(vis
[now
]) continue;vis
[now
]=1;for(int i
=1;i
<=m
;i
++){if((now
&ned
[i
])!=ned
[i
]||(now
&no
[i
])) continue;int to
=now
;to
|=add
[i
];to
&=(S
-del
[i
]);if(dis
[to
]>dis
[now
]+val
[i
]){dis
[to
]=dis
[now
]+val
[i
];q
.push(mkp(dis
[to
],to
));}}}return;
}
signed main(){#ifndef ONLINE_JUDGE#endifn
=read();m
=read();mi
[0]=1;for(int i
=1;i
<=n
;i
++) mi
[i
]=mi
[i
-1]<<1;S
=mi
[n
]-1;for(int k
=1;k
<=m
;k
++){val
[k
]=read();scanf(" %s %s",s1
+1,s2
+1);for(int i
=1;i
<=n
;i
++){if(s1
[i
]=='+') ned
[k
]|=mi
[i
-1];if(s1
[i
]=='-') no
[k
]|=mi
[i
-1];if(s2
[i
]=='+') add
[k
]|=mi
[i
-1];if(s2
[i
]=='-') del
[k
]|=mi
[i
-1];}}dij();printf("%d\n",dis
[0]<inf
?dis
[0]:0);return 0;
}
總結
以上是生活随笔為你收集整理的洛谷P2761:软件补丁问题(状压、分层图最短路)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。