题面
https://www.luogu.org/problem/P2761
题解
状态压缩+最短路+动态边(写的是没加动态边的90分版)
话说今年$NOI2019$ $D2$ $T1$ $kd-tree$不写动态边炸成52分。。。
#include<cstdio> #include<iostream> #include<cstring> #include<vector> #include<queue> #include<cstdlib> #define ri register int #define N (1<<21) using namespace std; int n,m; int d; int sta; string s1,s2; bool vis[N]; int dis[N]; vector<int> to[N],len[N]; void add_edge(int a,int b,int c) { to[a].push_back(b); len[a].push_back(c); } void link(int cur,int sta) { if (cur==n) { int ret=sta; for (ri i=0;i<n;i++) { if (s2[i]=='-' && (ret&(1<<i))) ret^=(1<<i); if (s2[i]=='+' && (!(ret&(1<<i)))) ret^=(1<<i); } if (sta!=ret) add_edge(sta,ret,d); return; } if (s1[cur]=='+') link(cur+1,sta+(1<<cur)); else if (s1[cur]=='-') link(cur+1,sta); else link(cur+1,sta),link(cur+1,sta+(1<<cur)); } struct node { int u,d; bool operator < (const node &rhs) const { return d>rhs.d; } }; void dijkstra() { priority_queue<node> q; memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[(1<<n)-1]=0; q.push((node){(1<<n)-1,0}); while (!q.empty()) { int x=q.top().u; q.pop(); if (vis[x]) continue; if (x==0) { printf("%d ",dis[x]); exit(0); } vis[x]=1; for (ri i=0;i<to[x].size();i++) { int y=to[x][i]; if (dis[y]>dis[x]+len[x][i]) { dis[y]=dis[x]+len[x][i]; q.push((node){y,dis[y]}); } } } } int main(){ ios::sync_with_stdio(false); cin>>n>>m; for (ri i=1;i<=m;i++) { cin>>d>>s1>>s2; link(0,0); } dijkstra(); if (dis[0]>1e9) dis[0]=0; cout<<dis[0]<<endl; }