zoukankan      html  css  js  c++  java
  • 【BZOJ 3049】【USACO2013 Jan】Island Travels BFS+状压DP

    这是今天下午的互测题,只得了60多分

    分析一下错因:

      $dis[i][j]$只记录了相邻的两个岛屿之间的距离,我一开始以为可以,后来$charge$提醒我有可能会出现来回走的情况,而状压转移就一次,无法实现来回走的情况,所以加了一个类似$floyed算法$的三重循环来更新每个点的距离,然后状态转移就可以了,枚举起点和终点,最后统计答案

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    char c[53][53];
    int n, m, dis[18][18], belong[53][53], f[40000][18], cnt = 0, qx[2500000], qy[2500000];
    int far[2500000], head, tail;
    bool vis[53][53];
    inline void _(int x, int y) {
    	belong[x][y] = cnt;
    	vis[x][y] = 1;
    	if (x > 1 && c[x - 1][y] == 'X' && !vis[x - 1][y])
    		_(x - 1, y);
    	if (y > 1 && c[x][y - 1] == 'X' && !vis[x][y - 1])
    		_(x, y - 1);
    	if (x < n && c[x + 1][y] == 'X' && !vis[x + 1][y])
    		_(x + 1, y);
    	if (y < m && c[x][y + 1] == 'X' && !vis[x][y + 1])
    		_(x, y + 1);
    }
    inline void __(int x) {
    	int nowx, nowy;
    	while (head != tail) {
    		++head; if ( head >= 2500000) head %= 2500000;
    		nowx = qx[head];
    		nowy = qy[head];
    		if (nowx > 1 && !vis[nowx - 1][nowy] && c[nowx - 1][nowy] != '.') {
    			if (c[nowx - 1][nowy] == 'S') {
    				++tail; if (tail >= 2500000) tail %= 2500000;
    				qx[tail] = nowx - 1;
    				qy[tail] = nowy;
    				far[tail] = far[head] + 1;
    				vis[nowx - 1][nowy] = 1;
    			} else {
    				dis[x][belong[nowx - 1][nowy]] = min( dis[x][belong[nowx - 1][nowy]], far[head]);
    			}
    		}
    		if (nowy > 1 && !vis[nowx][nowy - 1] && c[nowx][nowy - 1] != '.') {
    			if (c[nowx][nowy - 1] == 'S') {
    				++tail; if (tail >= 2500000) tail %= 2500000;
    				qx[tail] = nowx;
    				qy[tail] = nowy - 1;
    				far[tail] = far[head] + 1;	
    				vis[nowx][nowy - 1] = 1;			
    			} else {
    				dis[x][belong[nowx][nowy - 1]] = min( dis[x][belong[nowx][nowy - 1]], far[head]);
    			}
    		}
    		if (nowx < n && !vis[nowx + 1][nowy] && c[nowx + 1][nowy] != '.') {
    			if (c[nowx + 1][nowy] == 'S') {
    				++tail; if (tail >= 2500000) tail %= 2500000;
    				qx[tail] = nowx + 1;
    				qy[tail] = nowy;
    				far[tail] = far[head] + 1;
    				vis[nowx + 1][nowy] = 1;
    			} else {
    				dis[x][belong[nowx + 1][nowy]] = min( dis[x][belong[nowx + 1][nowy]], far[head]);
    			}			
    		}
    		if (nowy < m && !vis[nowx][nowy + 1] && c[nowx][nowy + 1] != '.') {
    			if (c[nowx][nowy + 1] == 'S') {
    				++tail; if (tail >= 2500000) tail %= 2500000;
    				qx[tail] = nowx;
    				qy[tail] = nowy + 1;
    				far[tail] = far[head] + 1;
    				vis[nowx][nowy + 1] = 1;
    			} else {
    				dis[x][belong[nowx][nowy + 1]] = min( dis[x][belong[nowx][nowy + 1]], far[head]);
    			}
    		}
    	}
    }
    int main() {
    	scanf("%d%d
    ", &n, &m);
    	for(int i = 1; i <= n; ++i)
    		for(int j = 1; j <= m; ++j) {
    			c[i][j] = getchar();
    			while (c[i][j] != 'X' && c[i][j] != '.' && c[i][j] != 'S')
    				c[i][j] = getchar();
    		}
    	memset(vis, 0, sizeof(vis));
    	for(int i = 1; i <= n; ++i)
    		for(int j = 1; j <= m; ++j)
    			if (!vis[i][j] && c[i][j] == 'X') {
    				++cnt;
    				_(i, j);
    			}
    	memset(dis, 1, sizeof(dis));
    	for(int i = 1; i <= cnt; ++i) {
    		head = 0;
    		tail = 0;
    		memset(vis, 0, sizeof(vis));
    		for(int k = 1; k <= n; ++k)
    			for(int l = 1; l <= m; ++l)
    				if (belong[k][l] == i) {
    					vis[k][l] = 1;
    					++tail; if ( tail >= 2500000) tail %= 2500000;
    					qx[tail] = k;
    					qy[tail] = l;
    					far[tail] = 0;
    				}
    		__(i);
    	}
        for(int k = 1; k <= cnt; ++k)
            for(int i = 1; i <= cnt; ++i)
                for(int j = 1; j <= cnt; ++j)
                    if (dis[i][k] + dis[k][j] < dis[i][j])
                        dis[i][j] = dis[i][k] + dis[k][j];
    	memset(f, 1, sizeof(f));
    	int ans = 500000, tot = (1 << cnt) - 1;
    	for(int i = 1; i <= cnt; ++i)
    		f[1 << ( i - 1)][i] = 0;
    	for(int i = 1; i <= tot; ++i) {
    		for(int j = 1; 1 << (j - 1) <= i; ++j) {
    			if (1 << (j - 1) & i) {
    				for(int k = 1; k <= cnt; ++k)
    					if (k != j && (1 << (k - 1) & i))
    						f[i][j] = min(f[i][j], f[i ^ (1 << (j - 1))][k] + dis[k][j]);
    			}
    		}
    	}
    	for(int i = 1; i <= cnt; ++i)
    		ans = min(ans, f[tot][i]);
    	printf("%d
    ",ans);
    	return 0;
    }
    

    以后思维得更严谨才行

    我的BFS写的就是这么丑,这又怎样?

  • 相关阅读:
    AngularJS
    Java
    Java
    AngularJS
    Java
    Java
    AngularJS
    Java
    Debian
    Java
  • 原文地址:https://www.cnblogs.com/abclzr/p/5334265.html
Copyright © 2011-2022 走看看