[codeforces 1301D] Time to Run 画图+周期性+你也可以

Codeforces Round #619 (Div. 2)

[codeforces 1301D] Time to Run 画图+周期性+你也可以

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

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

ProblemLangVerdictTimeMemory
D - Time to Run GNU C++11Accepted31 ms0 KB

笔者如此繁杂的代码,估计很少有人能看得下去。

写此文的目的,告诉各位,I believe I can.

不用看他人代码,思路,各位也一定能编码成功,开始慢一点,不要紧,信心是一点一点建立的。

比较好奇,该题的输出答案五花八门,codeforces是如何判断代码正确与否。望读者不吝赐教。

//明确是个欧拉回路,也即一笔画,该问题,具体到任意一点,入度与出度之和为0
//接下来,画图找规律,确保能经过所有道路。
//基本确认,画图有周期性
//但是a string of moves s of length at most 4.这个4挺难办,要是再大些就更好了
//start from the top-left cell.起点被限,也挺烦。
//存在多种可能的走法,找到符合题意的走法,注意限制a string of moves s of length at most 4.
//因n,m都可以从1开始的,所以该题还得先讨论n,m的范围。
//k>4nm-2n-2m无解。
//讨论n==1
//讨论m==1
//讨论n>=2&&m>=2

由图发现规律如下:

1个周期(上图中1,2,3或者4,5,6对应的路径): m-2个RDU,1个RD(1行);m-1个L;1个UD

边界(上图中7对应的路径).//m-1 R;n-1 U;m-1 L;

编码过程中,提供一组测试样例

AC代码如下

#include <stdio.h>
int n,m,k,a,b;
void period(int m){//1个周期
	if(m-2>0)printf("%d RDU\n",m-2);
	printf("1 RD\n");
	printf("%d L\n",m-1);
	printf("1 UD\n");
}
void solve(int n,int m,int k){//n>=2,m>=2,k<=4*n*m-2*n-2*m
	int p,step,tot,i;//p一个周期走过的道路数量.tot周期数量
	p=(m-2)*3+1*2+(m-1)*1+1*2;//1个周期: m-2个RDU,1个RD(1行);m-1个L;1个UD
	step=(m-2>0)+1+1+1;
	tot=n-1;
	if(k<=tot*p){//在周期范畴内
		a+=(k/p)*step,b=k%p;
		if(b){
			if(b<=(m-2)*3){
				if(b%3==0){//整除
					a+=1;
					printf("%d\n",a);
					for(i=1;i<=k/p;i++)period(m);
					printf("%d RDU\n",b/3);
				}else{//不整除
					a+=2;
					printf("%d\n",a);
					for(i=1;i<=k/p;i++)period(m);
					printf("%d RDU\n",b/3);
					b%=3;//此处关键,之前错写成b-=(m-2-1)*3;
					if(b==1)printf("1 R\n");
					else if(b==2)printf("1 RD\n");
				}
			}else if(b<=(m-2)*3+1*2){
				if(m-2>0)a+=2;
				else a+=1;//m-2==0
				printf("%d\n",a);
				for(i=1;i<=k/p;i++)period(m);
				if(m-2>0)printf("%d RDU\n",m-2);
				b-=(m-2)*3;
				if(b==1)printf("1 R\n");
				else if(b==2)printf("1 RD\n");
			}else if(b<=(m-2)*3+1*2+(m-1)*1){
				b-=(m-2)*3+1*2;
				if(m-2>0)a+=1+1+1;
				else a+=1+1;//m-2==0
				printf("%d\n",a);
				for(i=1;i<=k/p;i++)period(m);
				if(m-2>0)printf("%d RDU\n",m-2);
				printf("1 RD\n");
				printf("%d L\n",b);
			}else if(b<=(m-2)*3+1*2+(m-1)*1+1){
				if(m-2>0)a+=1+1+1+1;
				else a+=1+1+1;
				printf("%d\n",a);
				for(i=1;i<=k/p;i++)period(m);
				if(m-2>0)printf("%d RDU\n",m-2);
				printf("1 RD\n");
				printf("%d L\n",m-1);
				printf("1 U\n");
			}
		}else{//b==0
			printf("%d\n",a);
			for(i=1;i<=k/p;i++)period(m);
		}
	}else{//k>tot*p要讨论到边界.//m-1 R;n-1 U;m-1 L;
		a+=(k/p)*step,b=k%p;
		if(b<=(m-1)*1){
			a+=1;
			printf("%d\n",a);
			for(i=1;i<=k/p;i++)period(m);
			printf("%d R\n",b);
		}else if(b<=(m-1)*1+(n-1)*1){
			a+=2;
			printf("%d\n",a);
			for(i=1;i<=k/p;i++)period(m);
			printf("%d R\n",m-1);
			b-=m-1;
			printf("%d U\n",b);
		}else if(b<=(m-1)*1+(n-1)*1+(m-1)*1){
			a+=3;
			printf("%d\n",a);
			for(i=1;i<=k/p;i++)period(m);
			printf("%d R\n",m-1);
			printf("%d U\n",n-1);
			b-=(m-1)+(n-1);
			printf("%d L\n",b);
		}
	}
}
int main(){
	int i,j;
	scanf("%d%d%d",&n,&m,&k);
	if(k>4*n*m-2*n-2*m){//NO的唯一情况,也同时排除了n==1&&m==1的情况
		printf("NO\n");
		return 0;
	}
	printf("YES\n");
	if(n==1){
		if(k<=m-1){//一行水平行进最大距离m-1
			printf("1\n");
			printf("%d R\n",k);
		}
		else{ //k>m-1
			printf("2\n");
			printf("%d R\n",m-1);
			printf("%d L\n",k-(m-1));
		}
	}else if(m==1){//一列竖直行进最大距离n-1
		if(k<=n-1){
			printf("1\n");
			printf("%d D\n",k);
		}else{//k>n-1
			printf("2\n");
			printf("%d D\n",n-1);
			printf("%d U\n",k-(n-1));
		}
	}else if(n>=2&&m>=2) solve(n,m,k);//重点编写,因此种情况复杂,放在一个函数里,比较清晰
	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值