斯坦纳树是一类比较特殊的DP吧,主要针对点集连通问题,通常dp[i][s]表示以i为根的,连通状态为s的一棵树的最小权值,有两种转移方式,
其中state[i]表示点i的二进制标号,通常无关的点state值为0,
dp[i][s] = min{dp[i][s], dp[i][j] + dp[i][k]},这里是针对state[i]非0
dp[i][s] = min{dp[j][s] + dist(i, j), dp[i][s]},这里针对state[i]为0的点的转移方程。
更详细的分析在这里:http://endlesscount.blog.163.com/blog/static/821197872012525113427573/
UVALive 5717
Peach Blossom Spring
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 //Template updates date: 20140316 2 #include <iostream> 3 #include <sstream> 4 #include <cstdio> 5 #include <climits> 6 #include <ctime> 7 #include <cctype> 8 #include <cstring> 9 #include <cstdlib> 10 #include <string> 11 #include <stack> 12 #include <set> 13 #include <map> 14 #include <cmath> 15 #include <vector> 16 #include <queue> 17 #include <algorithm> 18 #define esp 1e-6 19 #define pi acos(-1.0) 20 #define inf 0x0f0f0f0f 21 #define pb push_back 22 #define lson l, m, rt<<1 23 #define rson m+1, r, rt<<1|1 24 #define lowbit(x) (x&(-x)) 25 #define mp(a, b) make_pair((a), (b)) 26 #define bit(k) (1<<(k)) 27 #define in freopen("solve_in.txt", "r", stdin); 28 #define out freopen("solve_out.txt", "w", stdout); 29 30 #define bug puts("********))))))"); 31 #define inout in out 32 33 #define SET(a, v) memset(a, (v), sizeof(a)) 34 #define SORT(a) sort((a).begin(), (a).end()) 35 #define REV(a) reverse((a).begin(), (a).end()) 36 #define READ(a, n) {REP(i, n) cin>>(a)[i];} 37 #define REP(i, n) for(int i = 0; i < (n); i++) 38 #define Rep(i, base, n) for(int i = base; i < n; i++) 39 #define REPS(s, i) for(int i = 0; s[i]; i++) 40 #define pf(x) ((x)*(x)) 41 #define mod(n) ((n)) 42 #define Log(a, b) (log((double)b)/log((double)a)) 43 #define Srand() srand((int)time(0)) 44 #define random(number) (rand()%number) 45 #define random_range(a, b) (int)(((double)rand()/RAND_MAX)*(b-a) + a) 46 47 using namespace std; 48 typedef long long LL; 49 typedef unsigned long long ULL; 50 typedef vector<int> VI; 51 typedef pair<int,int> PII; 52 typedef vector<PII> VII; 53 typedef vector<PII, int> VIII; 54 typedef VI:: iterator IT; 55 typedef map<string, int> Mps; 56 typedef map<int, int> Mpi; 57 typedef map<int, PII> Mpii; 58 typedef map<PII, int> Mpiii; 59 const int maxn = (1<<10); 60 const int maxm = 50 + 10; 61 int dp[maxm][maxn], ans[maxn], s[maxm]; 62 struct EDGE { 63 int to, w; 64 EDGE *next; 65 EDGE() {} 66 EDGE(int to, int w, EDGE *next):to(to), w(w), next(next) {} 67 }*head[maxm], E[2000 + 10], *now; 68 int n, m, kk, L; 69 int IN[maxm][maxn]; 70 queue<int> q; 71 void add(int u, int v, int w) { 72 now->to = v; 73 now->w = w; 74 now->next = head[u]; 75 head[u] = now; 76 now++; 77 } 78 void pre() { 79 now = E; 80 L = (1<<(2*kk)); 81 SET(head, 0); 82 for(int i = 0; i < m; i++) { 83 int u, v, w; 84 scanf("%d%d%d", &u, &v,&w); 85 add(u, v, w); 86 add(v, u, w); 87 } 88 memset(s, 0, sizeof(s)); 89 for(int i = 0; i < L; i++) 90 for(int j = 1; j <= n; j++) 91 dp[j][i] = inf; 92 for(int i = 1; i <= kk; i++) { 93 s[i] = 1<<(i-1); 94 dp[i][s[i]] = 0; 95 s[n-i+1] = 1<<(kk+i-1); 96 dp[n-i+1][s[n-i+1]] = 0; 97 } 98 99 } 100 bool check(int x) { 101 int ans = 0; 102 for(int i = 0; i < 2*kk; x >>= 1, i++) 103 ans += (x&1)*(i < kk ? 1 : -1); 104 return ans == 0; 105 } 106 bool go(int x, int y, int w) { 107 if(dp[x][y] > w) 108 return dp[x][y] = w, true; 109 return false; 110 } 111 void spfa() { 112 while(!q.empty()) { 113 int x = q.front()/10000; 114 int y = q.front()%10000; 115 IN[x][y] = 0; 116 q.pop(); 117 for(EDGE *next = head[x]; next; next = next->next) { 118 if(go(next->to, y|s[next->to], dp[x][y] + next->w) && !s[next->to] && !IN[next->to][y]) 119 IN[next->to][y] = 1, q.push(next->to*10000 + y); 120 } 121 } 122 } 123 int main() { 124 125 int T; 126 for(int t = scanf("%d" ,&T); t <= T; t++) { 127 scanf("%d%d%d", &n, &m, &kk); 128 pre(); 129 memset(IN, 0, sizeof(IN)); 130 for(int i = 0; i < L; i++) { 131 for(int j = 1; j <= n; j++) { 132 for(int st = i; st; st = (st-1)&i) 133 dp[j][i] = min(dp[j][i], dp[j][st|s[j]] + dp[j][(i-st)|s[j]]); 134 if(dp[j][i] < inf) 135 IN[j][i] = 1, q.push(j*10000 + i); 136 } 137 spfa(); 138 } 139 for(int i = 0; i < L; i++) { 140 ans[i] = inf; 141 for(int j = 1; j <= n; j++) { 142 ans[i] = min(ans[i], dp[j][i]); 143 } 144 } 145 for(int i = 1; i < L; i++) 146 if(check(i)) 147 for(int j = i; j ; j = (j-1)&i) 148 if(check(j)) 149 ans[i] = min(ans[i], ans[j] + ans[i-j]); 150 if(ans[L-1] < inf) 151 cout<<ans[L-1]<<endl; 152 else cout<<"No solution"<<endl; 153 } 154 return 0; 155 }
题意:有n个行星上有工厂,m个行星上有资源,每个资源行星只能给一个工厂提供资源,给定行星间的连接关系,
最多能有多少个工厂能够运行,而且花费的费用最少。
与上面的题目变化在于最后DP的时候check里面改成工厂数目不少于资源行星数目就行了。
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 //Template updates date: 20140316 2 #include <iostream> 3 #include <sstream> 4 #include <cstdio> 5 #include <climits> 6 #include <ctime> 7 #include <cctype> 8 #include <cstring> 9 #include <cstdlib> 10 #include <string> 11 #include <stack> 12 #include <set> 13 #include <map> 14 #include <cmath> 15 #include <vector> 16 #include <queue> 17 #include <algorithm> 18 #define esp 1e-6 19 #define inf 0x0f0f0f0f 20 #define pi acos(-1.0) 21 #define pb push_back 22 #define lson l, m, rt<<1 23 #define rson m+1, r, rt<<1|1 24 #define lowbit(x) (x&(-x)) 25 #define mp(a, b) make_pair((a), (b)) 26 #define bit(k) (1<<(k)) 27 #define in freopen("solve_in.txt", "r", stdin); 28 #define out freopen("solve_out.txt", "w", stdout); 29 30 #define bug puts("********))))))"); 31 #define inout in out 32 33 #define SET(a, v) memset(a, (v), sizeof(a)) 34 #define SORT(a) sort((a).begin(), (a).end()) 35 #define REV(a) reverse((a).begin(), (a).end()) 36 #define READ(a, n) {REP(i, n) cin>>(a)[i];} 37 #define REP(i, n) for(int i = 0; i < (n); i++) 38 #define Rep(i, base, n) for(int i = base; i < n; i++) 39 #define REPS(s, i) for(int i = 0; s[i]; i++) 40 #define pf(x) ((x)*(x)) 41 #define mod(n) ((n)) 42 #define Log(a, b) (log((double)b)/log((double)a)) 43 #define Srand() srand((int)time(0)) 44 #define random(number) (rand()%number) 45 #define random_range(a, b) (int)(((double)rand()/RAND_MAX)*(b-a) + a) 46 47 using namespace std; 48 typedef long long LL; 49 typedef unsigned long long ULL; 50 typedef vector<int> VI; 51 typedef pair<int,int> PII; 52 typedef vector<PII> VII; 53 typedef vector<PII, int> VIII; 54 typedef VI:: iterator IT; 55 typedef map<string, int> Mps; 56 typedef map<int, int> Mpi; 57 typedef map<int, PII> Mpii; 58 typedef map<PII, int> Mpiii; 59 60 const int maxn = 222; 61 const int maxm = 5555; 62 const int LI = 1<<10; 63 64 int dp[maxn][LI], d[LI], s[maxn], num[maxn], vis[maxn], inq[maxn][LI]; 65 int n, m; 66 VI Store; 67 queue<int> q; 68 struct EDGE { 69 int v, w; 70 EDGE *nxt; 71 EDGE() {} 72 EDGE(int v, int w, EDGE *nxt):v(v), w(w), nxt(nxt) {} 73 } *head[maxn], E[maxm*2], *now; 74 void pre() { 75 SET(head, 0); 76 SET(dp, 0x0f); 77 SET(d, 0x0f); 78 SET(s, 0); 79 SET(inq, 0); 80 Store.clear(); 81 now = E; 82 } 83 void addedge(int u, int v, int w) { 84 now->v = v; 85 now->w = w; 86 now->nxt = head[u]; 87 head[u] = now++; 88 } 89 void read() { 90 for(int i = 1; i <= n; i++) { 91 int u, v; 92 scanf("%d%d", &u, &v); 93 if(u || v) 94 Store.pb(i); 95 num[i] = u; 96 vis[i] = v; 97 } 98 for(int i = scanf("%d", &m); i <= m; i++) { 99 int u, v, w; 100 scanf("%d%d%d", &u, &v, &w); 101 addedge(u, v, w); 102 addedge(v, u, w); 103 } 104 } 105 bool check(int x, int &b) { 106 int a; 107 a = b = 0; 108 for(int i = 0; x; i++, x >>= 1) 109 if(x&1) { 110 a += num[Store[i]]; 111 b += vis[Store[i]]; 112 } 113 return a >= b; 114 } 115 bool update(int x, int y, int w) { 116 if(dp[x][y] > w) 117 return dp[x][y] = w, true; 118 return false; 119 } 120 void spfa() { 121 while(!q.empty()) { 122 int u = q.front(); 123 q.pop(); 124 int x = u/10000; 125 int y = u%10000; 126 inq[x][y] = 0; 127 for(EDGE *p = head[x]; p; p = p->nxt) { 128 if(update(p->v, y|s[p->v], dp[x][y] + p->w) && s[p->v] == 0 && !inq[p->v][y]) 129 inq[p->v][y] = 1, q.push(p->v*10000 + y); 130 } 131 } 132 } 133 void solve() { 134 REP(i, Store.size()) { 135 s[Store[i]] = 1<<i; 136 dp[Store[i]][s[Store[i]]] = 0; 137 } 138 int L = 1<<Store.size(); 139 REP(state, L) { 140 Rep(i, 1, n+1) { 141 for(int st = state; st; st = (st-1)&state) 142 dp[i][state] = min(dp[i][state], dp[i][st|s[i]] + dp[i][(state-st)|s[i]]); 143 if(dp[i][state] < inf) 144 inq[i][state] = 1, q.push(i*10000 + state); 145 } 146 spfa(); 147 } 148 d[0] = 0; 149 int tmp, maxans, mincost; 150 maxans = 0, mincost = 0; 151 REP(i, L) Rep(j, 1, n+1) 152 d[i] = min(d[i], dp[j][i]); 153 Rep(i, 1, L) if(check(i, tmp)) 154 for(int j = i; j; j = (j-1)&i) 155 if(check(j, tmp) && check(i-j, tmp)) 156 d[i] = min(d[i], d[j] + d[i-j]); 157 REP(i, L) if(check(i, tmp) && (tmp > maxans || (tmp == maxans && d[i] < mincost))) 158 maxans = tmp, mincost = d[i]; 159 printf("%d %d\n", maxans, mincost); 160 } 161 int main() { 162 163 while(scanf("%d", &n) == 1) { 164 pre(); 165 read(); 166 solve(); 167 } 168 return 0; 169 }
不过一开始把题意看成每个资源行星可以给一个行星上所有工厂提供资源,这样一写发现还是可以写出来的,哈哈,倒是自己重新发明了一道题目。
思路是,需要枚举是哪些行星上工厂可以运行,然后算出相应工厂数目,以及这样的情况下,花费最少,由于最多4个行星上有工厂,所以这样暴力是可以的。
既然写了上一下这样的题意的代码,不能保证没有bug啊。
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 //Template updates date: 20140316 2 #include <iostream> 3 #include <sstream> 4 #include <cstdio> 5 #include <climits> 6 #include <ctime> 7 #include <cctype> 8 #include <cstring> 9 #include <cstdlib> 10 #include <string> 11 #include <stack> 12 #include <set> 13 #include <map> 14 #include <cmath> 15 #include <vector> 16 #include <queue> 17 #include <algorithm> 18 #define esp 1e-6 19 #define pi acos(-1.0) 20 #define pb push_back 21 #define lson l, m, rt<<1 22 #define rson m+1, r, rt<<1|1 23 #define lowbit(x) (x&(-x)) 24 #define mp(a, b) make_pair((a), (b)) 25 #define bit(k) (1<<(k)) 26 #define in freopen("solve_in.txt", "r", stdin); 27 #define out freopen("solve_out.txt", "w", stdout); 28 29 #define bug puts("********))))))"); 30 #define inout in out 31 32 #define SET(a, v) memset(a, (v), sizeof(a)) 33 #define SORT(a) sort((a).begin(), (a).end()) 34 #define REV(a) reverse((a).begin(), (a).end()) 35 #define READ(a, n) {REP(i, n) cin>>(a)[i];} 36 #define REP(i, n) for(int i = 0; i < (n); i++) 37 #define Rep(i, base, n) for(int i = base; i < n; i++) 38 #define REPS(s, i) for(int i = 0; s[i]; i++) 39 #define pf(x) ((x)*(x)) 40 #define mod(n) ((n)) 41 #define Log(a, b) (log((double)b)/log((double)a)) 42 #define Srand() srand((int)time(0)) 43 #define random(number) (rand()%number) 44 #define random_range(a, b) (int)(((double)rand()/RAND_MAX)*(b-a) + a) 45 46 using namespace std; 47 typedef long long LL; 48 typedef unsigned long long ULL; 49 typedef vector<int> VI; 50 typedef pair<int,int> PII; 51 typedef vector<PII> VII; 52 typedef vector<PII, int> VIII; 53 typedef VI:: iterator IT; 54 typedef map<string, int> Mps; 55 typedef map<int, int> Mpi; 56 typedef map<int, PII> Mpii; 57 typedef map<PII, int> Mpiii; 58 59 const int maxn = 222; 60 const int maxm = 5555; 61 const int LI = 1<<10; 62 int s[maxn], inq[maxn][LI]; 63 LL dp[maxn][LI], d[LI], cost[maxn]; 64 LL inf; 65 66 int n, m; 67 LL maxans, mincost, L, temp; 68 VI planetA, planetB; 69 int cntA, cntB, Minx; 70 queue<int> q; 71 72 struct EDGE { 73 int v; 74 LL w; 75 EDGE *nxt; 76 EDGE() {} 77 EDGE(int v, LL w, EDGE *nxt):v(v), w(w), nxt(nxt) {} 78 } *head[maxn], E[maxm*2], *now; 79 80 void addedge(int u, int v, int w) { 81 now->v = v; 82 now->w = w; 83 now->nxt = head[u]; 84 head[u] = now++; 85 } 86 int maze[5][5][10]= {{}, {{},{1}},{{},{1,2},{3}},{{},{1,2,4},{3,6,5},{7}}, 87 {{},{1,2,4,8},{3,5,9,6,10,12},{7,11,13,14},{15}} 88 }; 89 void pre() { 90 now = E; 91 SET(head, 0); 92 SET(s, 0); 93 SET(cost, 0); 94 SET(&inf, 0x0f); 95 maxans = 0; 96 mincost = 0; 97 temp = 0; 98 planetA.clear(); 99 planetB.clear(); 100 planetA.pb(-1); 101 planetB.pb(-1); 102 cntA = cntB = 0; 103 } 104 void read() { 105 Rep(i, 1, n+1) { 106 int u, v; 107 scanf("%d%d", &u, &v); 108 if(u&&v) { 109 temp += u; 110 } else { 111 if(u) 112 planetA.pb(i), cntA++, cost[i] = u; 113 if(v)planetB.pb(i), cntB++; 114 } 115 } 116 for(int i = scanf("%d", &m); i <= m; i++) { 117 int u, v, w; 118 scanf("%d%d%d", &u, &v, &w); 119 addedge(u, v, (LL)w); 120 addedge(v, u, (LL)w); 121 } 122 } 123 LL encode(int m, int l, int j) { 124 SET(dp, 0x0f),SET(d, 0x0f); 125 LL ans = 0; 126 SET(s, 0); 127 int cnt1 = 0, cnt2 = 0; 128 for(int i = 1; i <= cntA; i++) 129 if(maze[cntA][m][l]&(1<<(i-1))) { 130 ans += cost[planetA[i]]; 131 s[planetA[i]] = (1<<(cnt1++)); 132 dp[planetA[i]][s[planetA[i]]] = 0; 133 } 134 for(int i = 1; i <= cntB; i++) 135 if(maze[cntB][m][j]&(1<<(i-1))) { 136 s[planetB[i]] = (1<<(cnt2++)); 137 if(s[planetB[i]] < (1<<(m))) 138 s[planetB[i]] += ((1<<m)-1); 139 dp[planetB[i]][s[planetB[i]]] = 0; 140 } 141 return ans; 142 } 143 bool update(int x, int y, LL w) { 144 if(dp[x][y] > w) 145 return dp[x][y] = w, true; 146 return false; 147 } 148 void spfa() { 149 while(!q.empty()) { 150 int u = q.front(); 151 q.pop(); 152 int x = u/20000; 153 int y = u%20000; 154 inq[x][y] = 0; 155 for(EDGE *p = head[x]; p; p = p->nxt) { 156 if(update(p->v, y|s[p->v], dp[x][y]+p->w) && (y|s[p->v] == y) && !inq[p->v][y]) 157 inq[p->v][y] = 1, q.push(p->v*20000 + y); 158 } 159 } 160 } 161 bool check(int x) { 162 int ans = 0; 163 for(int i = 0; x; x >>= 1, i++) 164 ans += (i < Minx ? 1 : -1)*(x&1); 165 return ans == 0; 166 } 167 void solve() { 168 Minx = min(cntA,cntB); 169 while(Minx) { 170 L = (1<<(2*Minx)); 171 for(int i = 0; maze[cntA][Minx][i]; i++) 172 for(int j = 0; maze[cntB][Minx][j]; j++) { 173 LL tmp = encode(Minx, i, j); 174 SET(inq, 0); 175 for(int state = 0; state < L; state++) { 176 for(int x = 1; x <= n; x++) { 177 for(int st = state; st; st = (st-1)&state) 178 dp[x][state] = min(dp[x][state], dp[x][st|s[x]] + dp[x][s[x]|(state-st)]); 179 if(dp[x][state] < inf) 180 inq[x][state] = 1, q.push(x*20000 + state); 181 } 182 spfa(); 183 } 184 for(int i = 0; i < L; i++) 185 for(int j = 1; j <= n; j++) 186 d[i] = min(d[i], dp[j][i]); 187 d[0] = 0; 188 for(int i = 1; i < L; i++) 189 if(check(i)) 190 for(int j = i; j; j = (j-1)&i) 191 if(check(j)) 192 d[i] = min(d[i], d[j] + d[i-j]); 193 194 if(d[L-1] < inf && (tmp > maxans || (tmp == maxans && d[L-1] < mincost))) 195 maxans = tmp, mincost = d[L-1]; 196 } 197 Minx--; 198 } 199 maxans += temp; 200 printf("%lld %lld\n", maxans, mincost); 201 } 202 int main() { 203 204 while(scanf("%d", &n) != EOF) { 205 pre(); 206 read(); 207 solve(); 208 } 209 return 0; 210 }
给定n*m矩阵,一些格子为景点,要求选择一些格子使得景点之间两两连通,非景点的格子上必须安排相应数目志愿者。
这个题目只不过变成了点带权值,所以进行第一种状态转移时,应该注意减去重复计算的权值,然后最后发现记录路径的时候不会,
看了别人代码发现还是太年轻,直接把中间过渡状态记录最后一步步回溯,记录相应格子就是了。
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 //Template updates date: 20140316 2 #include <iostream> 3 #include <sstream> 4 #include <cstdio> 5 #include <climits> 6 #include <ctime> 7 #include <cctype> 8 #include <cstring> 9 #include <cstdlib> 10 #include <string> 11 #include <stack> 12 #include <set> 13 #include <map> 14 #include <cmath> 15 #include <vector> 16 #include <queue> 17 #include <algorithm> 18 #define esp 1e-6 19 #define inf 0x0f0f0f0f 20 #define pi acos(-1.0) 21 #define pb push_back 22 #define lson l, m, rt<<1 23 #define rson m+1, r, rt<<1|1 24 #define lowbit(x) (x&(-x)) 25 #define mp(a, b) make_pair((a), (b)) 26 #define bit(k) (1<<(k)) 27 #define in freopen("solve_in.txt", "r", stdin); 28 #define out freopen("solve_out.txt", "w", stdout); 29 30 #define bug puts("********))))))"); 31 #define inout in out 32 33 #define SET(a, v) memset(a, (v), sizeof(a)) 34 #define SORT(a) sort((a).begin(), (a).end()) 35 #define REV(a) reverse((a).begin(), (a).end()) 36 #define READ(a, n) {REP(i, n) cin>>(a)[i];} 37 #define REP(i, n) for(int i = 0; i < (n); i++) 38 #define Rep(i, base, n) for(int i = base; i < n; i++) 39 #define REPS(s, i) for(int i = 0; s[i]; i++) 40 #define pf(x) ((x)*(x)) 41 #define mod(n) ((n)) 42 #define Log(a, b) (log((double)b)/log((double)a)) 43 #define Srand() srand((int)time(0)) 44 #define random(number) (rand()%number) 45 #define random_range(a, b) (int)(((double)rand()/RAND_MAX)*(b-a) + a) 46 47 using namespace std; 48 typedef long long LL; 49 typedef unsigned long long ULL; 50 typedef vector<int> VI; 51 typedef pair<int,int> PII; 52 typedef vector<PII> VII; 53 typedef vector<PII, int> VIII; 54 typedef VI:: iterator IT; 55 typedef map<string, int> Mps; 56 typedef map<int, int> Mpi; 57 typedef map<int, PII> Mpii; 58 typedef map<PII, int> Mpiii; 59 60 const int maxn = 11; 61 const int LI = 1<<11; 62 63 int maze[maxn][maxn], dp[maxn*maxn][LI], inq[maxn*maxn][LI], s[maxn*maxn], vis[maxn][maxn]; 64 int n, m, L ,id; 65 int pre[maxn*maxn][LI]; 66 char ans[maxn][maxn]; 67 int dx[] = {-1, 0, 1, 0}; 68 int dy[] = {0, 1, 0, -1}; 69 queue<int> q; 70 VI po; 71 72 bool check(int x,int y) { 73 return x >= 0 && x < n && y >= 0 && y < m; 74 } 75 bool update(int x, int y, int w) { 76 if(dp[x][y] > w) return dp[x][y] = w, true; 77 return false; 78 } 79 void ID(int x, int y) { 80 s[x*m+y] = 1<<id; 81 dp[x*m+y][s[x*m+y]] = 0; 82 po.pb(x*m+y); 83 id++; 84 } 85 void preprocess() { 86 po.clear(); 87 SET(inq, 0); 88 SET(vis, 0); 89 SET(s, 0); 90 SET(pre, -1); 91 SET(dp, 0x0f); 92 id = 0; 93 } 94 void spfa() { 95 96 while(!q.empty()) { 97 int u = q.front(); 98 q.pop(); 99 int x = u/2000; 100 int y = u%2000; 101 inq[x][y] = 0; 102 int xx = x/m; 103 int yy = x%m; 104 105 REP(k, 4) { 106 int nx = xx + dx[k]; 107 int ny = yy + dy[k]; 108 if(!check(nx, ny)) 109 continue; 110 int v = nx*m + ny; 111 if(update(v, y|s[v], dp[x][y] + maze[nx][ny]) ) { 112 pre[v][y|s[v]] = u; 113 if(!s[v] && !inq[v][y]) 114 inq[v][y] = 1, q.push(v*2000 + y); 115 } 116 } 117 } 118 } 119 void solve() { 120 L = 1<<id; 121 REP(state, L) { 122 REP(i, n) REP(j, m) { 123 int u = i*m+j; 124 for(int st = state; st; st = (st-1)&state){ 125 if(s[u] && !(s[u] & state)) 126 continue; 127 if(dp[u][state] > dp[u][st|s[u]] + dp[u][s[u]|(state-st)]-maze[i][j]) { 128 dp[u][state] = dp[u][st|s[u]] + dp[u][s[u]|(state-st)] - maze[i][j]; 129 pre[u][state] = u*2000 + (st|s[u]); 130 } 131 } 132 if(dp[u][state] < inf) 133 inq[u][state] = 1, q.push(u*2000 + state); 134 } 135 spfa(); 136 } 137 } 138 void BackTrace(int x, int y) { 139 int xx = x/m; 140 int yy = x%m; 141 vis[xx][yy] = 1; 142 int u = pre[x][y], nx, ny; 143 if(u == -1) 144 return; 145 nx = u/2000; 146 ny = u%2000; 147 BackTrace(nx, ny); 148 if(nx == x) 149 BackTrace(nx, (y-ny)|s[x]); 150 } 151 void output() { 152 if(id == 0 || dp[po[0]][L-1] == 0) { 153 cout<<0<<endl; 154 REP(i, n) { 155 REP(j, m) 156 putchar(ans[i][j]); 157 puts(""); 158 } 159 } else { 160 int tmp1 = dp[po[0]][L-1]; 161 cout<<tmp1<<endl; 162 BackTrace(po[0], L-1); 163 REP(i, n) { 164 REP(j, m) { 165 if(!maze[i][j]) 166 putchar('x'); 167 else if(vis[i][j]) 168 putchar('o'); 169 else putchar('_'); 170 } 171 puts(""); 172 } 173 } 174 } 175 int main() { 176 177 scanf("%d%d", &n, &m);{ 178 preprocess(); 179 REP(i, n) REP(j, m) { 180 scanf("%d", &maze[i][j]); 181 if(!maze[i][j]) 182 ID(i, j), ans[i][j] = 'x'; 183 else ans[i][j] = '_'; 184 } 185 solve(); 186 output(); 187 } 188 return 0; 189 }
HDU - 3311
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 //Template updates date: 20140316 2 #include <iostream> 3 #include <sstream> 4 #include <cstdio> 5 #include <climits> 6 #include <ctime> 7 #include <cctype> 8 #include <cstring> 9 #include <cstdlib> 10 #include <string> 11 #include <stack> 12 #include <set> 13 #include <map> 14 #include <cmath> 15 #include <vector> 16 #include <queue> 17 #include <algorithm> 18 #define esp 1e-6 19 #define inf 0x3f3f3f3f 20 #define pi acos(-1.0) 21 #define pb push_back 22 #define lson l, m, rt<<1 23 #define rson m+1, r, rt<<1|1 24 #define lowbit(x) (x&(-x)) 25 #define mp(a, b) make_pair((a), (b)) 26 #define bit(k) (1<<(k)) 27 #define in freopen("solve_in.txt", "r", stdin); 28 #define out freopen("solve_out.txt", "w", stdout); 29 30 #define bug puts("********))))))"); 31 #define inout in out 32 33 #define SET(a, v) memset(a, (v), sizeof(a)) 34 #define SORT(a) sort((a).begin(), (a).end()) 35 #define REV(a) reverse((a).begin(), (a).end()) 36 #define READ(a, n) {REP(i, n) cin>>(a)[i];} 37 #define REP(i, n) for(int i = 0; i < (n); i++) 38 #define Rep(i, base, n) for(int i = base; i < n; i++) 39 #define REPS(s, i) for(int i = 0; s[i]; i++) 40 #define pf(x) ((x)*(x)) 41 #define mod(n) ((n)) 42 #define Log(a, b) (log((double)b)/log((double)a)) 43 #define Srand() srand((int)time(0)) 44 #define random(number) (rand()%number) 45 #define random_range(a, b) (int)(((double)rand()/RAND_MAX)*(b-a) + a) 46 47 using namespace std; 48 typedef long long LL; 49 typedef unsigned long long ULL; 50 typedef vector<int> VI; 51 typedef pair<int,int> PII; 52 typedef vector<PII> VII; 53 typedef vector<PII, int> VIII; 54 typedef VI:: iterator IT; 55 typedef map<string, int> Mps; 56 typedef map<int, int> Mpi; 57 typedef map<int, PII> Mpii; 58 typedef map<PII, int> Mpiii; 59 60 const int maxn = 1100; 61 const int maxm = 5000*2 + 1000; 62 const int LI = (1<<10); 63 64 int dp[maxn][LI], d[LI], inq[maxn][LI], s[maxn], cost[maxn]; 65 int n, m, p; 66 int L; 67 queue<int> q; 68 69 struct EDGE { 70 int v, w; 71 EDGE *nxt; 72 EDGE() {} 73 EDGE(int v, int w, EDGE *nxt):v(v),w(w), nxt(nxt) {} 74 } *head[maxn], E[maxm], *cur; 75 76 void addedge(int u, int v, int w) { 77 cur->v = v; 78 cur->w = w; 79 cur->nxt = head[u]; 80 head[u] = cur++; 81 82 } 83 void preprocess() { 84 SET(head, 0); 85 cur = E; 86 SET(s, 0); 87 SET(inq, 0); 88 SET(dp, 0x3f); 89 SET(d, 0x3f); 90 L = 1<<n; 91 } 92 bool update(int x, int y, int w) { 93 if(dp[x][y] > w) return dp[x][y] = w, true; 94 return false; 95 } 96 void spfa() { 97 while(!q.empty()) { 98 int u = q.front(); 99 q.pop(); 100 int x = u/10000; 101 int y = u%10000; 102 inq[x][y] = 0; 103 for(EDGE *p = head[x]; p; p = p->nxt) { 104 if(update(p->v, y|s[p->v], dp[x][y] + p->w) && (y|s[p->v]) == y && !inq[p->v][y]) 105 inq[p->v][y] = 1, q.push(p->v*10000 + y); 106 } 107 } 108 } 109 void solve() { 110 REP(i, n+m) scanf("%d", &cost[1+i]); 111 REP(i, n) 112 s[i+1] = 1<<i, dp[1+i][s[i+1]] = 0; 113 REP(i, p) { 114 int u, v, w; 115 scanf("%d%d%d", &u, &v, &w); 116 addedge(u, v, w); 117 addedge(v, u, w); 118 } 119 Rep(state,1, L) { 120 Rep(i, 1, n+m+1) { 121 // if(s[i] && !(s[i] & state)) 122 // continue; 123 for(int st = state&(state-1); st; st = (st-1)&state) { 124 dp[i][state] = min(dp[i][state], dp[i][st|s[i]] + dp[i][(state-st)|s[i]]); 125 } 126 if(dp[i][state] < inf) 127 inq[i][state] = 1, q.push(i*10000 + state); 128 } 129 spfa(); 130 } 131 Rep(i, 1, L) 132 Rep(j, 1, n+m+1) 133 d[i] = min(d[i], dp[j][i] + cost[j]); 134 Rep(st, 1, L) 135 for(int ss = (st-1)&st; ss; ss = (ss-1)&st) 136 d[st] = min(d[st], d[ss] + d[st-ss]); 137 printf("%d\n", d[L-1]); 138 } 139 140 int main() { 141 142 while(scanf("%d%d%d", &n, &m, &p) == 3) { 143 preprocess(); 144 solve(); 145 } 146 return 0; 147 }
法二:用dp[i][s]表示以i为根且在i点挖井,连通状态为s的最小花费,不过转移时应该注意重复计算的cost[i],两种情况下的转移都要自习考虑
代码:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 //Template updates date: 20140316 2 #include <iostream> 3 #include <sstream> 4 #include <cstdio> 5 #include <climits> 6 #include <ctime> 7 #include <cctype> 8 #include <cstring> 9 #include <cstdlib> 10 #include <string> 11 #include <stack> 12 #include <set> 13 #include <map> 14 #include <cmath> 15 #include <vector> 16 #include <queue> 17 #include <algorithm> 18 #define esp 1e-6 19 #define inf 0x0f0f0f0f 20 #define pi acos(-1.0) 21 #define pb push_back 22 #define lson l, m, rt<<1 23 #define rson m+1, r, rt<<1|1 24 #define lowbit(x) (x&(-x)) 25 #define mp(a, b) make_pair((a), (b)) 26 #define bit(k) (1<<(k)) 27 #define in freopen("solve_in.txt", "r", stdin); 28 #define out freopen("solve_out.txt", "w", stdout); 29 30 #define bug puts("********))))))"); 31 #define inout in out 32 33 #define SET(a, v) memset(a, (v), sizeof(a)) 34 #define SORT(a) sort((a).begin(), (a).end()) 35 #define REV(a) reverse((a).begin(), (a).end()) 36 #define READ(a, n) {REP(i, n) cin>>(a)[i];} 37 #define REP(i, n) for(int i = 0; i < (n); i++) 38 #define Rep(i, base, n) for(int i = base; i < n; i++) 39 #define REPS(s, i) for(int i = 0; s[i]; i++) 40 #define pf(x) ((x)*(x)) 41 #define mod(n) ((n)) 42 #define Log(a, b) (log((double)b)/log((double)a)) 43 #define Srand() srand((int)time(0)) 44 #define random(number) (rand()%number) 45 #define random_range(a, b) (int)(((double)rand()/RAND_MAX)*(b-a) + a) 46 47 using namespace std; 48 typedef long long LL; 49 typedef unsigned long long ULL; 50 typedef vector<int> VI; 51 typedef pair<int,int> PII; 52 typedef vector<PII> VII; 53 typedef vector<PII, int> VIII; 54 typedef VI:: iterator IT; 55 typedef map<string, int> Mps; 56 typedef map<int, int> Mpi; 57 typedef map<int, PII> Mpii; 58 typedef map<PII, int> Mpiii; 59 const int maxn = 1100; 60 const int maxm = 5000*2 + 1000; 61 const int LI = (1<<10); 62 63 int dp[maxn][LI], d[LI], inq[maxn][LI], s[maxn], cost[maxn]; 64 int n, m, p; 65 int L; 66 queue<int> q; 67 68 struct EDGE { 69 int v, w; 70 EDGE *nxt; 71 EDGE() {} 72 EDGE(int v, int w, EDGE *nxt):v(v),w(w), nxt(nxt) {} 73 } *head[maxn], E[maxm], *cur; 74 75 void addedge(int u, int v, int w) { 76 u--, v--; 77 cur->v = v; 78 cur->w = w; 79 cur->nxt = head[u]; 80 head[u] = cur++; 81 82 } 83 void preprocess() { 84 SET(head, 0); 85 cur = E; 86 SET(s, 0); 87 SET(inq, 0); 88 SET(dp, 0x0f); 89 SET(d, 0x0f); 90 L = 1<<n; 91 } 92 bool update(int x, int y, int w) { 93 if(dp[x][y] >= w) return dp[x][y] = w, true; 94 return false; 95 } 96 void spfa() { 97 while(!q.empty()) { 98 int u = q.front(); 99 q.pop(); 100 int x = u/1000; 101 int y = u%1000; 102 inq[x][y] = 0; 103 for(EDGE *p = head[x]; p; p = p->nxt) { 104 if(update(p->v, y|s[p->v], dp[x][y] + p->w + cost[p->v]-cost[x]) && !s[p->v] && !inq[p->v][y]) 105 inq[p->v][y] = 1, q.push(p->v*1000 + y); 106 } 107 } 108 } 109 void solve() { 110 REP(i, n+m) scanf("%d", &cost[i]); 111 REP(i, n) 112 s[i] = 1<<i, dp[i][s[i]] = cost[i]; 113 REP(i, p) { 114 int u, v, w; 115 scanf("%d%d%d", &u, &v, &w); 116 addedge(u, v, w); 117 addedge(v, u, w); 118 } 119 REP(state, L) { 120 REP(i, n+m) { 121 if(s[i] && !(s[i] & state)) 122 continue; 123 for(int st = state; st; st = (st-1)&state) { 124 dp[i][state] = min(dp[i][state], dp[i][st|s[i]] + dp[i][(state-st)|s[i]] - cost[i]); 125 } 126 if(dp[i][state] < inf) 127 inq[i][state] = 1, q.push(i*1000 + state); 128 } 129 spfa(); 130 } 131 d[0] = 0; 132 REP(i, L) 133 REP(j, n+m) 134 d[i] = min(d[i], dp[j][i]); 135 Rep(st, 1, L) 136 for(int ss = (st-1)&st; ss; ss = (ss-1)&st) 137 d[st] = min(d[st], d[ss] + d[st-ss]); 138 cout<<d[L-1]<<endl; 139 } 140 141 int main() { 142 143 while(scanf("%d%d%d", &n, &m, &p) == 3) { 144 preprocess(); 145 solve(); 146 } 147 return 0; 148 }
看了别人发现其实还有一种方法就是虚拟一个点,然后连一条cost[i]的边到n+m个点,最后对0,1,2...n这n+1个点求斯坦纳树,可是好像怎么写都不对,
先挖坑。。。