
首先不同的地图最多只有16种了,每张地图可以组合的格式是
2
16
2^{16}
216 ,因为同一种地图变成全
1
1
1 的步骤是一样的,那么我们可以这么抽象,把一种不同的地图状态看成二进制的某一位,把一些地图的组合看成是一个点,要求的是最小花费,我们可以用全
1
1
1 的地图作为起点,向外拓展可以到达的点,那么就可以使用最短路求解。
具体的:令
d
i
s
[
x
]
dis[x]
dis[x] 表示到达
x
x
x 这个地图状态的最小花费 ,
x
x
x 在第
i
i
i 位是
1
1
1 代表的就是代表有第
i
i
i 张地图。我们可以定义
t
r
a
n
s
[
b
i
t
]
[
S
]
trans[bit][S]
trans[bit][S] 表示 当前有的地图集合是
S
S
S 进行
b
i
t
bit
bit 操作时变成的状态集合
S
′
S'
S′ .
b
i
t
bit
bit 是题目给的一行,一列等等的操作,具体是把
2
×
2
2\times 2
2×2 的格子从左到右,从上到下设为
1
,
2
,
4
,
8
1,2,4,8
1,2,4,8 ,那么比如说对上面一行操作,那就是一张地图的二进制表示异或上
3
3
3
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
using i128 = __int128;
#define int long long
constexpr int maxn = 1<<16;
constexpr int FULL = 15;
constexpr i64 inf = (1ll<<60);
int trans[16][maxn]; //S经过bit变化会变成什么
i64 dis[maxn];
bool vis[maxn];
vector<pair<int,int>> op;
int a0,a1,a2,a3;
inline int calc(string &s1,string &s2){
return (s1[0]=='1'?1 : 0) +
(s1[1]=='1'?2 : 0) +
(s2[0]=='1'?4 : 0) +
(s2[1]=='1'?8 : 0);
}
void solve(){
int n;cin>>n;
string s1,s2;
int S = 0;
for(int i = 0;i<n;++i){
cin>>s1>>s2;
S |= (1<<calc(s1,s2));
}
cout<<dis[S]<<'\n';
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);
int t=1;
cin>>t>>a0>>a1>>a2>>a3;
fill(dis,dis+maxn,inf);
for(int m = 0;m<16;++m){
for(int S = 0;S<maxn;++S){
int Y = 0;
for(int bit = 0;bit<16;++bit){
if((S>>bit)&1) Y|=(1<<(bit^m));
}
trans[m][S] = Y;
}
}
op.emplace_back(1,a0);
op.emplace_back(2,a0);
op.emplace_back(4,a0);
op.emplace_back(8,a0);
op.emplace_back(3,a1);
op.emplace_back(12,a1);
op.emplace_back(5,a2);
op.emplace_back(10,a2);
op.emplace_back(15,a3);
dis[0] = 0;
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> q;
q.emplace(0,0);//d u
while(!q.empty()){
auto [d,u] = q.top();
q.pop();
if(vis[u]) continue;
vis[u] = true;
for(auto &[m,w]:op){
int v1 = trans[m][u];
int v2 = trans[m][u|(1<<15)];//全1
if(dis[v1]>w+dis[u]){
dis[v1] = w + d;
q.emplace(dis[v1],v1);
}
if(dis[v2]>w+dis[u]){
dis[v2] = w + d;
q.emplace(dis[v2],v2);
}
}
}
while(t--) solve();
return 0;
}
突然发现之前的代码贴错了
1277

被折叠的 条评论
为什么被折叠?



