zoukankan      html  css  js  c++  java
  • 【POJ3133】Manhattan Wiring (插头dp)

    Manhattan Wiring

    题意:

    There is a rectangular area containing n × m cells. Two cells are marked with “2”, and another two with “3”. Some cells are occupied by obstacles. You should connect the two “2”s and also the two “3”s with non-intersecting lines. Lines can run only vertically or horizontally connecting centers of cells without obstacles.

    Lines cannot run on a cell with an obstacle. Only one line can run on a cell at most once. Hence, a line cannot intersect with the other line, nor with itself. Under these constraints, the total length of the two lines should be minimized. The length of a line is defined as the number of cell borders it passes. In particular, a line connecting cells sharing their border has length 1.
    大意:将2,2连接,3,3连接,两条路径不相交求长度最小值

    思路:

    因为只用求序列的最小值,所以也不需要记录括号序列,只用区分是连接(2)还是连接(3)

    (dp)中存四进制数,有1表示连2的插头,有2表示连3的插头,然后分开讨论

    (b_1)表示左插头的值,(b_2)表示上插头的值

    点为1

    只能转移空格子

    点为 2/3

    1、只有左插头或者上插头,标号相同时可以转移,代表是终点

    2、既没有左插头也没有右插头,加一个向右或者向下的插头,编号就是这个格子的值

    3、既有左又有上不合法

    点为0

    1、如果(!(b1|b2))

    ①不加

    ②加一个右和下插头,标号为2或3

    2、(b_1)&(b_2)

    ①如果标号相同,直接连上

    ②不相同,不合法

    3、(b_1|b_2)

    如果是左插头,多加向右或者向下的

    如果是上插头,同理

    最后的答案用最后一个点

    //POJ 3133
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    bool cur1;
    void Rd(int &res) {
    	res=0;
    	char c;
    	while(c=getchar(),c<48);
    	do res=(res<<1)+(res<<3)+(c^48);
    	while(c=getchar(),c>=48);
    }
    #define M 300005
    const int Mod=299987;
    int n,m,a[15][15],op,cnt[2],ex,ey,pr[1<<20],la[M],to[2][1<<20],inv[15],ans=0,dp[2][M];
    void Min(int &x,int y) {
    	if(x==-1||x>y)x=y;
    }
    void add(int bit,int v) {
    	int u=(bit%Mod)+1;
    	for(int i=la[u]; i; i=pr[i])
    		if(to[op][i]==bit) {
    			Min(dp[op][i],v);
    			return;
    		}
    	to[op][++cnt[op]]=bit,pr[cnt[op]]=la[u],la[u]=cnt[op],dp[op][cnt[op]]=v;
    }
    bool cur2;
    void Print(int x) {
    	for(int i=0; i<=m; i++)printf("%d",x%4),x>>=2;
    }
    int main() {
    	inv[0]=1;
    	for(int i=1; i<=10; i++)inv[i]=(inv[i-1]<<2);
    	while(1) {
    		Rd(n),Rd(m);
    		if(!(n|m))break;
    		int ex,ey;
    		for(int i=1; i<=n; i++)for(int j=1; j<=m; j++)Rd(a[i][j]);
    		for(int i=1;i<=n;i++)a[i][m+1]=1;
    		for(int j=1;j<=m;j++)a[n+1][j]=1;
    		memset(dp,63,sizeof(dp));
    		memset(la,0,sizeof(la));
    		int res=inv[m+1]-1;
    		op=0,cnt[0]=1,to[0][1]=0,dp[0][1]=0;
    		for(int i=1; i<=n; i++) {
    			for(int k=1; k<=cnt[op]; k++)to[op][k]<<=2,to[op][k]&=res;
    			for(int j=1; j<=m; j++) {
    				op^=1,cnt[op]=0,memset(la,0,sizeof(la));
    				for(int k=1; k<=cnt[op^1]; k++) {
    					int v=dp[op^1][k],od=to[op^1][k],b1=((od>>(2*(j-1)))%4),b2=((od>>(2*j))%4);
    					if(a[i][j]==1) {
    						if(!(b1|b2))add(od,v);
    					} else if(!a[i][j]) {
    						if(!(b1|b2)) {
    							add(od,v);
    							if((a[i][j+1]!=1)&&(a[i+1][j]!=1))add(od+inv[j-1]+inv[j],v+1),add(od+2*inv[j-1]+2*inv[j],v+1);
    						} else if(b1&&b2) {
    							if(b1==b2)add(od-inv[j-1]*b1-inv[j]*b2,v+1);
    						} else if(b1) {
    							if(a[i+1][j]!=1)add(od,v+1);
    							if(a[i][j+1]!=1)add(od-inv[j-1]*b1+inv[j]*b1,v+1);
    						} else if(b2) {
    							if(a[i][j+1]!=1)add(od,v+1);
    							if(a[i+1][j]!=1)add(od+inv[j-1]*b2-inv[j]*b2,v+1);
    						}
    					} else {
    						if(!(b1|b2)) {
    							if(a[i][j+1]!=1)add(od+inv[j]*(a[i][j]-1),v+1);
    							if(a[i+1][j]!=1)add(od+inv[j-1]*(a[i][j]-1),v+1);
    						} else if(b1&&b2);
    						else if(b1) {
    							if(b1==a[i][j]-1)add(od-inv[j-1]*b1,v+1);
    						} else {
    							if(b2==a[i][j]-1)add(od-inv[j]*b2,v+1);
    						}
    					}
    				}
    			}
    		}
    		int ans=-1;
    		for(int k=1; k<=cnt[op]; k++)if(!to[op][k])Min(ans,dp[op][k]);
    		if(ans==-1)puts("0");
    		else printf("%d
    ",ans-2);
    	}
    	return 0;
    }
    
  • 相关阅读:
    typescript学习记录-基础类型(3)
    typescript学习记录-基础语法(2)
    typescript学习记录-介绍与环境(1)
    elementUI中的日历组件(DatePicker)怎样单独设置默认年和默认月
    怎样保持div中的子元素的长宽比例展示
    大批量端口扫描、服务识别
    域环境搭建
    sed 替换换行符
    zmap/masscan 快速扫描网络
    内网渗透——代理和转发
  • 原文地址:https://www.cnblogs.com/cly1231/p/13019001.html
Copyright © 2011-2022 走看看