CodeM2018 初赛A轮 第1,2题

CodeM2018 初赛A

今晚参加了CodeM2018初赛A,结果只做对了两题……

第1题:求一段字符串对应手机按键移动最少次数。

送分题非常简单,我的解法是一个数组保存A-Z的按键,一个二维数组保存按键之间的距离。读入字符串只需要记住当前的和它的前一个字母,查表加和。排行榜上的大佬们2-5分钟就写完提交,但我实在没那么快。

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main(){
	int i,j,k,n,T,f,sum;
	int latterMap[26]={1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,6,7,7,7,8,8,8,8};
	int distMap[9][9]=
	{{0,1,2,1,2,3,2,3,4},
	 {1,0,1,2,1,2,3,2,3},
	 {2,1,0,3,2,1,4,3,2},
	 {1,2,3,0,1,2,1,2,3},
	 {2,1,2,1,0,1,2,1,2},
	 {3,2,1,2,1,0,3,2,1},
	 {2,3,4,1,2,3,0,1,2},
	 {3,2,3,2,1,2,1,0,1},
	 {4,3,2,3,2,1,2,1,0}};
	char c,c0,xx[3];
	scanf("%d",&T);gets(xx);
	for(k=0;k<T;k++){
		f=0;sum=0;
		while(scanf("%c",&c)==1 && c!='\n'){
			printf("c=%c\n",c);
			if(f==0){
				sum+=distMap[0][latterMap[c-'A']];
				f=1;
			}else sum+=distMap[latterMap[c0-'A']][latterMap[c-'A']];
			c0=c;
		}
		printf("%d\n",sum);
	}
	return 0;
}

第2题: 一个1*n的棋盘上,每个格子放着一些棋子,每个棋子可以向左移,或者向左移动到最左边以后再向右移,给出棋子总数相同的状态A和B,求状态转换需要移动的次数。

这个题本来设想的是从左到右扫描,把第一个状态的棋子挨个转换为第二个状态,移动次数相加。但是提交不对,就去玩了半个时,时间浪的差不多了回来再看,然后发现了这样不对:

应该先从右向左遍历第一个状态的所有棋子,把其中能够只通过左移就能达到第二状态的棋子先减去,然后再从左向右次数相加,再注意数据大小就能通过。

可能这样设想的比较麻烦,大佬们应该有更简便的做法。另外在自己电脑VS根本开不了这么大数组,都是小数组编好,在提交时候再把数组改大。

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int min(int a,int b){
	return a<b?a:b;
}
int main(){
	int i,j,k,n,f;
	long long ans=0;
	int a[100010],b[100010],num,done,x;
	scanf("%d",&n); 
	if(n==1){printf("0\n");return 0;}
	memset(a,0,sizeof(a));b[0]=0;
	for(i=1;i<=n;i++)scanf("%d",&a[i]);
	for(i=1;i<=n;i++)scanf("%d",&b[i]);
	i=n;j=n;
	while(i>0 && j>0){
		while(a[i]==0 && i>0)i--;
		while(b[j]==0 && j>0)j--;
		while(i<j && j>0)j--;
		if(i>=j){
			if(a[i]>=b[j]){
				ans=ans+b[j]*(long long)(i-j);
				a[i]=a[i]-b[j];
				b[j]=0;
				j--;
			}
			if(a[i]<=b[j]){
				ans=ans+a[i]*(long long)(i-j);
				b[j]=b[j]-a[i];
				a[i]=0;
				i--;
			}
		}
	}
	for(i=1;i<=n;i++)a[i]=a[i-1]+a[i];
	j=1;done=0;
	for(i=1;i<=n;i++){
		num=b[i];
		b[i]=b[i-1]+b[i];
		if(num!=0){
			while(b[i]>=a[j] && j<=n){
				if(i<=j){
					x=min(b[i]-done,(a[j]-done));
					ans=ans+x*(long long)(j-i);
					done=done+x;
				}
				else if(i>j){
					x=min(b[i]-done,(a[j]-done));
					ans=ans+x*(long long)(j+i-2);
					done=done+x;
				}
				j++;
			}
			if(j<=n && b[i]>a[j-1] && b[i]<a[j]){
				if(i<=j){
					x=min(b[i]-done,(a[j]-done));
					ans=ans+x*(long long)(j-i);
					done=done+x;
				}else if(i>j){
					x=min(b[i]-done,(a[j]-done));
					ans=ans+x*(long long)(j+i-2);
					done=done+x;
				}
			}
		}
	}
	printf("%lld\n",ans);
	return 0;
}

后面题目没来得及看了,最终排名前600,只有前250名才能进复赛,又看了一下去年初赛B轮比A轮难一些,估计复赛无望了(望天)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值