原题链接
状压 + 最短路.
1.建议多用 ‘(’, ‘)’ 避免区分运算符优先级.
2.不用邻接表,时间换空间.
代码如下:
#include <bits/stdc++.h>
using namespace std;
#define ll int
#define pli pair<ll, int>
const int N = 22, NN = 1 << 20, M = 4001000;
int n, m;
// int head[NN], nex[M], ver[M], val[M], tot = 1;
char a[N], b[N];
ll d[NN + 1];
bool v[NN];
priority_queue<pli, vector<pli>, greater<pli> > q;
struct Debug {
int s1, s2, s3, s4, t;
};
Debug c[105];
void print(int x) {
for (int i = 1; i <= n; ++i) {
printf("%d", x >> (i - 1) & 1);
}
}
/*
void add(int x, int y, int z) {
// print(x); putchar(' '); print(y); putchar(' '); printf("%d\n", z);
ver[++tot] = y; val[tot] = z; nex[tot] = head[x]; head[x] = tot;
} */
void Dij() {
memset(d, 0x3f, sizeof d);
d[0] = 0; q.push({0ll, 0});
while (q.size()) {
int x = q.top().second; q.pop();
if (v[x]) continue;
v[x] = 1;
for (int j = 1; j <= m; ++j) {
int s1 = c[j].s1, s2 = c[j].s2, s3 = c[j].s3, s4 = c[j].s4;
if (((s2 & x) == s2) && ((x & s1) == 0)) {
int y = (x | s3) & s4; ll z = c[j].t;
if (d[y] > d[x] + z) {
d[y] = d[x] + z;
q.push({d[y], y});
}
}
}
}
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; ++i) {
int t;
scanf("%d", &t);
scanf("%s%s", a + 1, b + 1);
int s1 = 0, s2 = 0, s3 = 0, s4 = 0;
for (int j = 1; j <= n; ++j) {
if (b[j] == '-') s3 |= (1 << (j - 1));
if (b[j] != '+') s4 |= (1 << (j - 1));
}
for (int j = 1; j <= n; ++j) {
if (a[j] == '-') s2 |= (1 << (j - 1));
else if (a[j] != '0') s1 |= (1 << (j - 1));
}
c[i] = {s1, s2, s3, s4, t};
// print(s1); putchar(' '); print(s2); putchar(' '); print(s3); putchar(' '); print(s4); putchar('\n');
}
Dij();
printf("%lld", d[(1 << n) - 1] == d[NN] ? 0ll : d[(1 << n) - 1]);
}