标签:bre vector 输出 需要 左右 space mes void turn
分析题意,我们首先需要知道这样一个性质:图形的任意两种状态之间是可以相互转换的。
也就是说,没有哪种状态是初始状态不能变化到的;同理,也没有哪种状态是终止状态不能变化到的。
此外我们还可以发现,变化步骤是可以倒推的。
结合以上几点,就可以得到这道题的做法了。
首先我们需要找到一个中间状态,为了方便,我们将这个中间状态定为所有点联向$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\n",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\n",su,sv,eu,ev,i);
}
}
return;
}
void Print() {
printf("%d\n",cnt1+cnt2);
for(int i=1;i<=cnt1;i++) {
printf("%d %d\n",op1[i].frm,op1[i].to);
}
for(int i=cnt2;i>=1;i--) {
printf("%d %d\n",op2[i].frm,op2[i].to);
}
return;
}
int main()
{
Read();
Solve();
Print();
return 0;
}
标签:bre vector 输出 需要 左右 space mes void turn
原文地址:https://www.cnblogs.com/luoshui-tianyi/p/12194582.html