代码改变世界
[登录 · 注册]
  • [LA3620]Manhattan Wiring
  • [LA3620]Manhattan Wiring

    试题描述

    输入

    输出

    输入示例

    5 5
    0 0 0 0 0
    0 0 0 3 0
    2 0 2 0 0
    1 0 1 1 1
    0 0 0 0 3
    2 3
    2 2 0
    0 3 3
    6 5
    2 0 0 0 0
    0 3 0 0 0
    0 0 0 0 0
    1 1 1 0 0
    0 0 0 0 0
    0 0 2 3 0
    5 9
    0 0 0 0 0 0 0 0 0
    0 0 0 0 3 0 0 0 0
    0 2 0 0 0 0 0 2 0
    0 0 0 0 3 0 0 0 0
    0 0 0 0 0 0 0 0 0
    9 9
    3 0 0 0 0 0 0 0 2
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0
    2 0 0 0 0 0 0 0 3
    9 9
    0 0 0 1 0 0 0 0 0
    0 2 0 1 0 0 0 0 3
    0 0 0 1 0 0 0 0 2
    0 0 0 1 0 0 0 0 3
    0 0 0 1 1 1 0 0 0
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0
    9 9
    0 0 0 0 0 0 0 0 0
    0 3 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 2 3 2
    0 0

    输出示例

    18
    2
    17
    12
    0
    52
    43

    数据规模及约定

    见“输入

    题解

    我们把“连线”的过程改为“铺地砖”的过程,总共有 11 种地砖,每种地砖上的图案连接了两个不同的边界,或只触碰了一个边界,或没有图案,具体见下图:

    其中,有障碍的格子只能铺 0 号砖,有数字 2 或 3 的格子只能铺 1 到 4 号砖,空地可以铺 0 或 5 到 10 号砖。

    然后我们就可以轮廓线 dp 了,把状态表示成上一行的底部是否有线,这一行的底部是否有线,当前格子的左边是否有线,具体见下图:

    带绿点的格子表示当前格子。那么上图的状态就是 (02000100)3 了(我习惯先读上面一行,再读下面一行,最后读竖直边上的数字),注意这里 2 连出的线与 3 连出的线进行了区分,因为不能让 2 和 3 连到一起。

    转移的时候需要判断一些不合法情况:线头接到了没有线头和它相连的地方,不同类型线头接在了一起,或是有一个线头等你去接而你没有理它。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
    	if(Head == Tail) {
    		int l = fread(buffer, 1, BufferSize, stdin);
    		Tail = (Head = buffer) + l;
    	}
    	return *Head++;
    }
    int read() {
    	int x = 0, f = 1; char c = Getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
    	return x * f;
    }
    
    #define maxn 15
    #define maxs 59060
    #define maxb 11
    #define oo 2147483647
    
    struct Blo {
    	bool L, U, R, D; int v;
    	Blo() {}
    	Blo(bool _l, bool _u, bool _r, bool _d, int _v): L(_l), U(_u), R(_r), D(_d), v(_v) {}
    } bls[maxb];
    int n, m, Map[maxn][maxn], f[maxn][maxn][maxs], tri[maxn];
    
    void up(int& a, int b) {
    	a = min(a, b);
    	return ;
    }
    
    char str[maxn];
    char* tri_(int x) {
    	int l = 0;
    	while(x) str[l++] = x % 3 + '0', x /= 3;
    	while(l <= m) str[l++] = '0';
    	str[l] = 0;
    	return str;
    }
    
    int main() {
    	bls[0] = Blo(0, 0, 0, 0, 0);
    	bls[1] = Blo(1, 0, 0, 0, 1);
    	bls[2] = Blo(0, 1, 0, 0, 1);
    	bls[3] = Blo(0, 0, 1, 0, 1);
    	bls[4] = Blo(0, 0, 0, 1, 1);
    	bls[5] = Blo(1, 1, 0, 0, 2);
    	bls[6] = Blo(1, 0, 1, 0, 2);
    	bls[7] = Blo(1, 0, 0, 1, 2);
    	bls[8] = Blo(0, 1, 1, 0, 2);
    	bls[9] = Blo(0, 1, 0, 1, 2);
    	bls[10] = Blo(0, 0, 1, 1, 2);
    	tri[0] = 1;
    	for(int i = 1; i < maxn; i++) tri[i] = tri[i-1] * 3;
    	
    	while(1) {
    		n = read(); m = read();
    		if(!n && !m) break;
    		
    		for(int i = 1; i <= n; i++)
    			for(int j = 1; j <= m; j++) Map[i][j] = read();
    		int all = tri[m+1] - 1;
    		for(int i = 1; i <= n + 1; i++)
    			for(int j = 1; j <= m; j++)
    				for(int S = 0; S <= all; S++) f[i][j][S] = oo;
    		f[1][1][0] = 0;
    		for(int i = 1; i <= n; i++)
    			for(int j = 1; j <= m; j++)
    				for(int S = 0; S <= all; S++) if(f[i][j][S] < oo) {
    //					printf("%d %d %s: %d
    ", i, j, tri_(S), f[i][j][S]);
    					if(Map[i][j] == 1) {
    						if(S % 3 || S / tri[m]) continue;
    						if(j < m) up(f[i][j+1][S/3%tri[m-1]], f[i][j][S] + bls[0].v);
    						else up(f[i+1][1][S/3%tri[m-1]], f[i][j][S] + bls[0].v);
    					}
    					if(Map[i][j] == 2) {
    						for(int c = 1; c <= 4; c++) {
    							if(S % 3 > 0 ^ bls[c].U > 0) continue;
    							if(S % 3 && S % 3 != 1) continue;
    							if(S / tri[m] > 0 ^ bls[c].L > 0) continue;
    							if(S / tri[m] && S / tri[m] != 1) continue;
    							if(j == m && bls[c].R) continue;
    							int tS = S / 3 % tri[m-1] + (int)bls[c].D * tri[m-1] + (int)bls[c].R * tri[m];
    							if(j < m) up(f[i][j+1][tS], f[i][j][S] + bls[c].v);
    							else up(f[i+1][1][tS], f[i][j][S] + bls[c].v);
    						}
    					}
    					if(Map[i][j] == 3) {
    						for(int c = 1; c <= 4; c++) {
    							if(S % 3 > 0 ^ bls[c].U > 0) continue;
    							if(S % 3 && S % 3 != 2) continue;
    							if(S / tri[m] > 0 ^ bls[c].L > 0) continue;
    							if(S / tri[m] && S / tri[m] != 2) continue;
    							if(j == m && bls[c].R) continue;
    							int tS = S / 3 % tri[m-1] + (int)bls[c].D * 2 * tri[m-1] + (int)bls[c].R * 2 * tri[m];
    							if(j < m) up(f[i][j+1][tS], f[i][j][S] + bls[c].v);
    							else up(f[i+1][1][tS], f[i][j][S] + bls[c].v);
    						}
    					}
    					if(!Map[i][j]) {
    						for(int c = 0; c <= 10; c ? c++ : (c = 5)) {
    							int tp = 0;
    							if(S % 3 > 0 ^ bls[c].U > 0) continue;
    							if(S % 3) tp = S % 3;
    							if(S / tri[m] > 0 ^ bls[c].L > 0) continue;
    							if(S / tri[m] && tp && S / tri[m] != tp) continue;
    							if(S / tri[m]) tp = S / tri[m];
    							if(j == m && bls[c].R) continue;
    							if(tp) {
    								int tS = S / 3 % tri[m-1] + (int)bls[c].D * tp * tri[m-1] + (int)bls[c].R * tp * tri[m];
    								if(j < m) up(f[i][j+1][tS], f[i][j][S] + bls[c].v);
    								else up(f[i+1][1][tS], f[i][j][S] + bls[c].v);
    							}
    							else for(tp = 1; tp <= 2; tp++) {
    								int tS = S / 3 % tri[m-1] + (int)bls[c].D * tp * tri[m-1] + (int)bls[c].R * tp * tri[m];
    								if(j < m) up(f[i][j+1][tS], f[i][j][S] + bls[c].v);
    								else up(f[i+1][1][tS], f[i][j][S] + bls[c].v);
    							}
    						}
    					}
    				}
    		
    		printf("%d
    ", f[n+1][1][0] < oo ? (f[n+1][1][0] >> 1) : 0);
    	}
    	
    	return 0;
    }
    

    代码贼难写。。。QAQ

  • 【推广】 阿里云小站-上云优惠聚集地(新老客户同享)更有每天限时秒杀!
    【推广】 云服务器低至0.95折 1核2G ECS云服务器8.1元/月
    【推广】 阿里云老用户升级四重礼遇享6.5折限时折扣!
  • 原文:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6959356.html
Copyright 2008-2020 晋ICP备12007731号-1