zoukankan      html  css  js  c++  java
  • 【UOJ #107】【APIO 2013】ROBOTS

    http://uoj.ac/problem/107
    (f(l,r,i,j))表示([l,r])中的机器人聚集到((i,j))需要花的最小操作数。
    (f(l,r,i,j)=minleft{egin{array}{rcl} f(l,k,i,j)+f(k+1,r,i,j)\ f(l,r,i',j'),(i',j') ightarrow(i,j)end{array} ight.)
    斯坦纳树的模型,对于每个([l,r])的状态,处理完第一行后再跑一遍双队列广搜处理第二行。
    用基数排序优化,时间复杂度(O(n^3+n^2hw))

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int N = 503;
    const int dx[4] = {-1, 0, 1, 0};
    const int dy[4] = {0, -1, 0, 1};
    
    struct data {
    	int x, y;
    	data (int _x = 0, int _y = 0) : x(_x), y(_y) {}
    } to[N][N][4];
    
    bool vis[N][N][4];
    char s[N][N];
    int f[10][10][N][N], n, w, h;
    
    data work(int x, int y, int tmp) {
    	if (vis[x][y][tmp]) return to[x][y][tmp];
    	vis[x][y][tmp] = true;
    	if (s[x][y] == 'A') (++tmp) &= 3;
    	if (s[x][y] == 'C') (--tmp) &= 3;
    	if (s[x + dx[tmp]][y + dy[tmp]] == 'x')
    		return data(x, y);
    	else
    		return to[x + dx[tmp]][y + dy[tmp]][tmp] = work(x + dx[tmp], y + dy[tmp], tmp);
    }
    
    int tot = 0, l, r, id[N * N];
    data q1[N * N], q2[N * N], tt;
    
    template <typename T> void check_min(T &a, T b) {if (b < a) a = b;}
    template <typename T> void check_max(T &a, T b) {if (b > a) a = b;}
    
    bool cmp(data A, data B) {return f[l][r][A.x][A.y] < f[l][r][B.x][B.y];}
    
    int c[N * N * 20];
    
    void BFS() {
    //	stable_sort(q1 + 1, q1 + tot + 1, cmp);
    	int mx = 0, num;
    	for (int i = 1; i <= tot; ++i) if ((num = f[l][r][q1[i].x][q1[i].y]) != 1010580540) check_max(mx, num);
    	memset(c, 0, sizeof(int) * (mx + 2));
    	for (int i = 1; i <= tot; ++i) {
    		num = f[l][r][q1[i].x][q1[i].y];
    		if (num != 1010580540) ++c[num];
    		else ++c[mx + 1];
    	}
    	for (int i = 1; i <= mx + 1; ++i) c[i] += c[i - 1];
    	for (int i = tot; i >= 1; --i) {
    		num = f[l][r][q1[i].x][q1[i].y];
    		if (num == 1010580540) num = mx + 1;
    		id[c[num]--] = i;
    	}
    	int head = 1, tail = 0, tmp = 1, x, y, x2, y2;
    	while (head <= tail || tmp <= tot) {
    		x = q2[head].x; y = q2[head].y;
    		x2 = q1[id[tmp]].x; y2 = q1[id[tmp]].y;
    		if (head <= tail && tmp <= tot && f[l][r][x][y] < f[l][r][x2][y2] || tmp > tot)	++head;
    		else ++tmp, x = x2, y = y2;
    		for (int d = 0; d < 4; ++d) {
    			tt = to[x][y][d];
    			if (tt.x == 0) continue;
    			if (f[l][r][tt.x][tt.y] > f[l][r][x][y] + 1) {
    				f[l][r][tt.x][tt.y] = f[l][r][x][y] + 1;
    				q2[++tail] = tt;
    			}
    		}
    	}
    }
    
    int main() {
    	scanf("%d%d%d", &n, &w, &h);
    	
    	memset(f, 60, sizeof(f));
    	
    	for (int i = 1; i <= h; ++i)
    		scanf("%s", s[i] + 1);
    	for (int i = 1; i <= h; ++i) s[i][0] = s[i][w + 1] = 'x';
    	for (int i = 1; i <= w; ++i) s[0][i] = s[h + 1][i] = 'x';
    	for (int i = 1 ; i <= h; ++i)
    		for (int j = 1; j <= w; ++j)
    			if (s[i][j] != 'x')
    				for (int dt = 0; dt < 4; ++dt)
    					to[i][j][dt] = work(i, j, dt);
    	
    	for (int i = 1; i <= h; ++i)
    		for (int j = 1; j <= w; ++j) q1[++tot] = data(i, j);
    	
    	bool flag;
    	for (int i = n; i >= 1; --i) {
    		flag = false;
    		for (int ii = 1; ii <= h; ++ii) {
    			for (int jj = 1; jj <= w; ++jj)
    				if (s[ii][jj] == '0' + i) {
    					f[i][i][ii][jj] = 0;
    					flag = true;
    					break;
    				}
    			if (flag) break;
    		}
    		l = r = i; BFS();
    		for (int j = i + 1; j <= n; ++j) {
    			for (int k = i; k < j; ++k)
    				for (int ii = 1; ii <= h; ++ii)
    					for (int jj = 1; jj <= w; ++jj)
    						check_min(f[i][j][ii][jj], f[i][k][ii][jj] + f[k + 1][j][ii][jj]);
    			l = i; r = j; BFS();
    		}
    	}
    	
    	int ans = 0x7fffffff;
    	for (int i = 1; i <= h; ++i)
    		for (int j = 1; j <= w; ++j)
    			check_min(ans, f[1][n][i][j]);
    	printf("%d
    ", ans == 1010580540 ? -1 : ans);
    	return 0;
    }
    
  • 相关阅读:
    How to change hostname on SLE
    How to install starDIct on suse OS?
    python logging usage
    How to reset password for unknow root
    How to use wget ?
    How to only capute sub-matched character by grep
    How to inspect who is caller of func and who is the class of instance
    How to use groovy script on jenkins
    Vim ide for shell development
    linux高性能服务器编程 (二) --IP协议详解
  • 原文地址:https://www.cnblogs.com/abclzr/p/6706229.html
Copyright © 2011-2022 走看看