【2012年中山纪念中学信息学竞赛初一选拔赛一】纪中游戏(d)

【2012年中山纪念中学信息学竞赛初一选拔赛一】纪中游戏(d)

(File IO): input:d.in output:d.out 时间限制: 1000 ms 空间限制: 262144 KB

【题目描述】
纪中的学生是很幸福的,因为纪中有很多课外活动,每一个学生都能找到施展才华的舞台。除了上面说的JBA外,每年还有元旦晚会、主持人大赛、形象大使、街舞比赛、心声晚会、每周一演等等很多活动。
最近纪中又推出一项益智类的游戏——玩骰子,骰子是一个立方体,数字1到6分布在6个面上(如图所示),而且对着的两个面上的数字之和等于7,也就是说6对着1,5对着2,4对着3。
在这里插入图片描述

  一开始骰子被放在一个R*C的棋盘的左上角格子上,骰子一开始的状态是:数字1在上面,1的右边是3,同样为上图所示(即上面为1,下面为6,左面为4,右面为3,前面为2,后面为5)。
   现在允许你进行以下操作:把骰子往右滚直到到达最后一列,然后把骰子往下滚到达下一行,再把骰子往左滚直到碰到第一列,然后把骰子往下滚到达下一行,再把骰子往右滚直到碰到最后一列,再把骰子往下滚到达下一行。。。,如此反复下去直到所有的格子都经过一次。
   要求计算到达所有格子时上面数字之和。

【输入】
第一行包含两个整数R和C(1<=R,C<=100,000)

【输出】
计算到达所有格子时上面数字之和。

【样例输入】
样例输入1
3 2
样例输入2
3 4
样例输入3
737 296

【样例输出】
样例输出1
19
样例输出2
42
样例输出3
763532

【数据范围限制】
50%的数据满足:1<=R,C<=100。

【提示】
样例1经过每个格子时骰子上面的数字依次为:1 4 5 1 3 5。

【思路】
用一个变量t[]来模拟每个格子当前是多少,接着去循环每一
行。如[1]=1,[2]=6,[3]=2,[4]=5,[5]=4,[6]=3
用双重循环来模拟,每滚一步,就判断i是否是奇数,如果是,就int tmp=a[0]; a[0]=a[4]; a[4]=a[1]; a[1]=a[5]; a[5]=tmp;否则就int tmp=a[0]; a[0]=a[5]; a[5]=a[1]; a[1]=a[4]; a[4]=tmp;,最后答案加上上面的
数。但还要竖着往下滚一次,同样,就int tp=a[0]; a[0]=a[3]; a[3]=a[1]; a[1]=a[2]; a[2]=tp;,最后输出答案。(这个规律大家拿个骰子滚一滚试一试也能发现)
看到这里,如果你打个代码试一试就会发现会超时!!!(哦对了还有记得用long long,否则你懂的!)
我们可以发现,这其实有重复的周期,每翻四次的和就是十四(具体大家自己思考)。所以我们可以进行优化,用此公式:ans+=(a[1]+a[2]+a[3]+a[4])*(c/4);
这样循环就可以减少很多次计算,从1~c%4就可以了。剩下部
分就和之前的一样了。

【AC代码】
1️⃣

#include<cstdio>
using namespace std;

long long r,c,t,ans = 0;
int a[6] = {1,6,2,5,4,3}; //上 下 前 后 右 左 

void roll_right(){
	int tmp = a[0];
	a[0] = a[4];
	a[4] = a[1];
	a[1] = a[5];
	a[5] = tmp; 
}

void roll_left(){
	int tmp = a[0];
	a[0] = a[5];
	a[5] = a[1];
	a[1] = a[4];
	a[4] = tmp;	
}

void roll_down(){
	int tmp = a[0];
	a[0] = a[3];
	a[3] = a[1];
	a[1] = a[2];
	a[2] = tmp;
}
int main()
{
	freopen("d.in","r",stdin);
	freopen("d.out","w",stdout); 
	scanf("%lld%lld",&r,&c);               //n行m列
	c--;                //骰子所在的位置不需要滚动,需要滚动的次数为c-1 
	for(int i = 1;i <= r;++i){
		ans += a[0];
		t = c / 4;                    //能滚多少次循环 
		ans += (a[0] + a[1] + a[2] + a[3]) * t;
		if(i % 2 == 1){               //当前在奇数行,向右滚 
			for(int j = 1;j <= c % 4;++j){
				roll_right();
				ans += a[0]; 
			}
		}
		else{                         //当前在偶数行,向左滚 
			for(int j = 1;j <= c % 4;++j){
				roll_left();
				ans += a[0];
			}
		}
		roll_down();   //向下滚到下一行 
	}
	printf("%lld",ans);
	fclose(stdin);
	fclose(stdout);
	return 0;
}

2️⃣

#include<iostream>
#include<cstdio>
using namespace std;
int a[]={1,6,2,5,4,3};
long long ans,t;
int main(){
	freopen("d.in","r",stdin);
	freopen("d.out","w",stdout);
	int r,c;
	cin>>r>>c;
	c--;
	for(int i=1;i<=r;i++){
		ans+=a[0];
		t=c/4;
		ans+=(a[0]+a[1]+a[2]+a[3])*t;
		if(i%2==1){
			for(int j=1;j<=c%4;j++){
				int tmp=a[0];
				a[0]=a[4];
				a[4]=a[1];
				a[1]=a[5];
				a[5]=tmp;
				ans+=a[0];
			}
		}else{
			for(int j=1;j<=c%4;j++){
				int tmp=a[0];
				a[0]=a[5];
				a[5]=a[1];
				a[1]=a[4];
				a[4]=tmp;
				ans+=a[0];
			}
		}
		int tp=a[0];
		a[0]=a[3];
		a[3]=a[1];
		a[1]=a[2];
		a[2]=tp;
	}
	cout<<ans;
	fclose(stdin);
	fclose(stdout);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值