[codeforces 1333D] Challenges in school №41 在整体移动中,记录个体移动的信息

Codeforces Round #632 (Div. 2)   比赛人数12810

[codeforces 1333D]   Challenges in school №41   在整体移动中,记录个体移动的信息

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址https://codeforces.com/contest/1333/problem/D

Problem Lang Verdict Time Memory
D - Challenges in school №41 GNU C++17 Accepted 358 ms 35500 KB

该题最大的亮点,就是,在整体移动中,记录个体移动的信息

手工算法如下

造了一组样例,如下
8 10
RRRLLRLL

字母数组脚标    12345678
原始数据        RRRLLRLL
第1次整体移动    RRLRLLRL记录移动的个体步骤(3,4),(6,7)        个体移动次数2次
第2次整体移动    RLRLRLLR记录移动的个体步骤(2,3),(4,5),(7,8)  个体移动次数3次
第3次整体移动    LRLRLRLR记录移动的个体步骤(1,2),(3,4),(5,6)  个体移动次数3次
第4次整体移动    LLRLRLRR记录移动的个体步骤(2,3),(4,5),(6,7)  个体移动次数3次
第5次整体移动    LLLRLRRR记录移动的个体步骤(3,4),(5,6)        个体移动次数2次
第6次整体移动    LLLLRRRR记录移动的个体步骤(4,5)              个体移动次数1次

可以看到最少移动次数6次
最多移动次数2+3+3+3+3+2+1=14次

k=10可这样操作
1 3
1 6
1 2
1 4
1 7
1 1
2 3 5
3 2 4 6
2 3 5
1 4

明白上述手工算法后,再结合如下AC代码,应该能很快解决该题。

#include <cstdio>
#include <algorithm>
#define maxn 3010
using namespace std;
int n,k,mx,mn;//mx最多步数,mn最少步数
char s[maxn];
int a[maxn][maxn];//a[i][j]表示在第i次整体移动中,对应的第j次个体移动.为了照顾程序的可读性,就不采用邻接表的方式进行记录了
int right[maxn];
int judge(){//返回值,1还需move,0无需move
	int i;
	for(i=1;i<n;i++)
		if(s[i]=='R'&&s[i+1]=='L')//存在面对面的情况
			return 1;
	return 0;
}
void move(){
	int i,r=0;
	mn++;//整体的移动次数
	for(i=1;i<n;i++)
		if(s[i]=='R'&&s[i+1]=='L'){//个体的移动
			mx++;//个体的移动次数
			r++;
			a[mn][r]=i;//记录一步一步的移动,对应的位置
		}
	for(i=1;i<=r;i++)swap(s[a[mn][i]],s[a[mn][i]+1]);//turns left and vice versa 就相当与交换
	right[mn]=r;
}
int main(){
	int l,r,i,j;
	scanf("%d%d%s",&n,&k,s+1);
	while(judge())move();
	if(k<mn||mx<k){printf("-1\n");return 0;}
	k-=mn;
	for(i=1;i<=mn;i++){//从整体移动中分解出独立步骤
		l=1,r=right[i];
		while(k&&l<r){//个体的移动
			printf("1 %d\n",a[i][l]);
			k--,l++;
		}
		printf("%d",r-l+1);//整体的移动
		for(j=l;j<=r;j++)printf(" %d",a[i][j]);
		printf("\n");
	}
	return 0;
}
发布了660 篇原创文章 · 获赞 562 · 访问量 48万+

猜你喜欢

转载自blog.csdn.net/mrcrack/article/details/105430662