zoukankan      html  css  js  c++  java
  • 【BZOJ 2595】【WC 2008】游览计划

    http://www.lydsy.com/JudgeOnline/problem.php?id=2595
    斯坦纳树的例题诶。。。我怎么做了好长时间_(:з」∠)_
    首先这是一棵树。
    状压表示状态,(f(i,j,s))表示连通的景点的状态为s,i和j为树根的最小值。
    转移时先在当前状态s上枚举s的子集t,用子集来转移(f(i,j,s)=min{f(i,j,t)+f(i,j,complement_st)-a(i,j)},tvarsubsetneqq s,t eqvarnothing)
    顺便把所有可以用来更新的状态加入队列,然后在当前枚举这层枚举的s内做spfa,求出其他点的f值。
    因为最优解一定可以通过两个没有重叠方块的连通块合并,所以不用担心求出的解会有方块被算多次。
    时间复杂度(O(2^kn^2m^2))

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define mk(x, y, z) ((x) + (y) * 100 + (z) * 10000)
    using namespace std;
    
    int a[13][13], f[13][13][1 << 10], pre[13][13][1 << 10], n, m, q[1000003], head, tail, inf, tot = 0, ans = 0x7fffffff;
    bool inq[10003], mark[13][13];
    
    const int dx[4] = {0, -1, 0, 1};
    const int dy[4] = {1, 0, -1, 0};
    
    void spfa(int s) {
    	int u, x, y, tx, ty, t;
    	while (head != tail) {
    		++head; if (head == 1000003) head = 0;
    		u = q[head]; inq[u] = false;
    		x = u % 100; y = u / 100;
    		for (int i = 0; i < 4; ++i) {
    			tx = x + dx[i]; ty = y + dy[i];
    			if (tx < 1 || tx > n || ty < 1 || ty > m) continue;
    			
    			t = f[x][y][s] + a[tx][ty];
    			if (t < f[tx][ty][s]) {
    				f[tx][ty][s] = t;
    				pre[tx][ty][s] = mk(x, y, s);
    				u = mk(tx, ty, 0);
    				if (!inq[u]) {
    					inq[u] = true;
    					++tail; if (tail == 1000003) tail = 0;
    					q[tail] = u;
    				}
    			}
    		}
    	}
    }
    
    void dfs(int x, int y, int s) {
    	mark[x][y] = true;
    	int num = pre[x][y][s]; if (num == 0) return;
    	if (num / 10000 == s)
    		dfs(num % 100, num / 100 % 100, s);
    	else {
    		dfs(x, y, num / 10000);
    		dfs(x, y, s ^ (num / 10000));
    	}
    }
    
    void ouit(int totnum) {
    	for (int i = 1; i <= n; ++i)
    		for (int j = 1; j <= m; ++j)
    			if (f[i][j][totnum] == ans) {
    				dfs(i, j, totnum);
    				return;
    			}
    }
    
    int main() {
    	scanf("%d%d", &n, &m);
    	memset(f, 60, sizeof(f)); inf = f[0][0][0];
    	for (int i = 1; i <= n; ++i)
    		for (int j = 1; j <= m; ++j) {
    			scanf("%d", &a[i][j]);
    			if (!a[i][j]) {
    				f[i][j][1 << tot] = 0;
    				++tot;
    			}
    		}
    	
    	int totnum = (1 << tot) - 1, now;
    	for (int s = 1; s <= totnum; ++s) {
    		head = tail = 0;
    		for (int i = 1; i <= n; ++i)
    			for (int j = 1; j <= m; ++j) {
    				for (int t = s & (s - 1); t; t = s & (t - 1)) {
    					now = f[i][j][t] + f[i][j][s ^ t] - a[i][j];
    					if (now < f[i][j][s]) {
    						f[i][j][s] = now;
    						pre[i][j][s] = mk(i, j, t);
    					}
    				}
    				if (f[i][j][s] != inf)
    					inq[q[++tail] = mk(i, j, 0)] = true;
    		}
    		spfa(s);
    	}
    	
    	for (int i = 1; i <= n; ++i)
    		for (int j = 1; j <= m; ++j)
    			ans = min(ans, f[i][j][totnum]);
    	printf("%d
    ", ans);
    	
    	ouit(totnum);
    	for (int i = 1; i <= n; ++i) {
    		for (int j = 1; j <= m; ++j)
    			if (mark[i][j])	putchar(a[i][j] ? 'o' : 'x');
    			else putchar('_');
    		puts("");
    	}
    	return 0;
    }
    
  • 相关阅读:
    CodeForces 288A Polo the Penguin and Strings (水题)
    CodeForces 289B Polo the Penguin and Matrix (数学,中位数)
    CodeForces 289A Polo the Penguin and Segments (水题)
    CodeForces 540C Ice Cave (BFS)
    网站后台模板
    雅图CAD
    mbps
    WCF学习-协议绑定
    数据库建表经验总结
    资源位置
  • 原文地址:https://www.cnblogs.com/abclzr/p/6184742.html
Copyright © 2011-2022 走看看