zoukankan      html  css  js  c++  java
  • CF512E Fox And Polygon

    CF512E Fox And Polygon

    分析题意,我们首先需要知道这样一个性质:图形的任意两种状态之间是可以相互转换的。
    也就是说,没有哪种状态是初始状态不能变化到的;同理,也没有哪种状态是终止状态不能变化到的。
    此外我们还可以发现,变化步骤是可以倒推的。
    结合以上几点,就可以得到这道题的做法了。
    首先我们需要找到一个中间状态,为了方便,我们将这个中间状态定为所有点联向$1$号点的情况。
    然后我们分别求出由初始状态变化为中间状态,和由终止状态变化为中间状态的步骤。
    这个找步骤的过程如下:
    枚举每个点,在这个点的左右两边分别找到一个与$1$点相连的点。根据分法(划分为数个三角形)可知,这两个点必然相连。然后删去这两点间的这条对角线并存储步骤即可。
    这里需要注意的是,新出现的对角线并不一定是$1$号点和当前枚举点的连线,所以要枚举找出这个同时与被删去对角线两端点相连的点。
    再这样一次操作后,当前枚举点不一定就会与$1$号点相连,所以要循环直到$1$号点和当前点相连为止,再枚举下一个点。
    用同样的方法找到由终止状态到中间状态的变化过程。注意存储的步骤是新出现对角线的两个端点
    最后输出所有步骤即可,其中由终止状态变化到中间状态的步骤需要倒序输出。
    (但是我现在还没证明步骤数必定在$20000$之内,所以记录步骤用vector会更好)

    #include<bits/stdc++.h>
    #define N 1010
    
    using namespace std;
    
    int n,cnt1,cnt2;
    bool edge1[N][N],edge2[N][N];
    
    struct node {
    	int frm,to;
    }op1[20010],op2[20010];
    
    void Read() {
    	scanf("%d",&n);
    	for(int i=1;i<=n-3;i++) {
    		int u,v;
    		scanf("%d%d",&u,&v);
    		edge1[u][v]=1;
    		edge1[v][u]=1;
    	}
    	for(int i=1;i<=n-3;i++) {
    		int u,v;
    		scanf("%d%d",&u,&v);
    		edge2[u][v]=1;
    		edge2[v][u]=1;
    	}
    	return;
    }
    
    void Solve() {
    	for(int i=1;i<=n;i++) {
    		edge1[i][i%n+1]=1;
    		edge1[i%n+1][i]=1;
    		edge2[i][i%n+1]=1;
    		edge2[i%n+1][i]=1;
    	}
    
    	for(int i=2;i<=n;i++) {
    		while(!edge1[1][i]) {
    			int su=i-1,sv,eu=0,ev; //su=i-1:i的上一个点必与1点相连 su-sv -> es-ev
    			for(int j=i+1;j<=n;j++) {
    				if(edge1[1][j]) {
    					sv=j;
    					break;
    				}
    			}
    			for(int k=1;k<=n;k++) {
    				if(edge1[su][k]&&edge1[sv][k]) {
    					if(eu==0) {
    						eu=k;
    					}
    					else {
    						ev=k;
    						break;
    					}
    				}
    			}
    			edge1[su][sv]=0;
    			edge1[sv][su]=0;
    			edge1[eu][ev]=1;
    			edge1[ev][eu]=1;
    			op1[++cnt1]=(node){su,sv};
    			//printf("op:%d %d %d %d i:%d
    ",su,sv,eu,ev,i);
    		}
    	}
    	for(int i=2;i<=n;i++) {
    		while(!edge2[1][i]) {
    			int su=i-1,sv,eu=0,ev; //su=i-1:i的上一个点必与1点相连 su-sv -> es-ev
    			for(int j=i+1;j<=n;j++) {
    				if(edge2[1][j]) {
    					sv=j;
    					break;
    				}
    			}
    			for(int k=1;k<=n;k++) {
    				if(edge2[su][k]&&edge2[sv][k]) {
    					if(eu==0) {
    						eu=k;
    					}
    					else {
    						ev=k;
    						break;
    					}
    				}
    			}
    			edge2[su][sv]=0;
    			edge2[sv][su]=0;
    			edge2[eu][ev]=1;
    			edge2[ev][eu]=1;
    			op2[++cnt2]=(node){eu,ev};
    			//printf("op:%d %d %d %d i:%d
    ",su,sv,eu,ev,i);
    		}
    	}
    
    	return;
    }
    
    void Print() {
    	printf("%d
    ",cnt1+cnt2);
    	for(int i=1;i<=cnt1;i++) {
    		printf("%d %d
    ",op1[i].frm,op1[i].to);
    	}
    	for(int i=cnt2;i>=1;i--) {
    		printf("%d %d
    ",op2[i].frm,op2[i].to);
    	}
    	return;
    }
    
    int main()
    {
    	Read();
    	Solve();
    	Print();
    	return 0;
    }
    
  • 相关阅读:
    网络受限下,使用Nexus要解决的两个问题
    Nexus远程Maven仓库索引下载教程
    maven--私服的搭建(Nexus的使用)
    maven命令/依赖/聚合
    mybatis常用jdbcType数据类型
    Lombok 安装、入门
    jquery append 动态添加的元素事件on 不起作用的解决方案
    Maximum Sum on Even Positions
    哈密顿
    计算几何基础
  • 原文地址:https://www.cnblogs.com/luoshui-tianyi/p/12194582.html
Copyright © 2011-2022 走看看