c语言算法的学习(指针,结构体,数学计算)

本文将从7道例题出发,讲述自己今天关于算法的学习

A - Maya Calendar

问题重述

上周末,M. A. Ya教授对古老的玛雅有了一个重大发现。从一个古老的节绳(玛雅人用于记事的工具)中,教授发现玛雅人使用Haab历法,一年有365天。Haab历法每年有19个月,在前18个月,每月有20天,月份的名字分别是pop, no, zip, zotz, tzec, xul, yoxkin,mol, chen, yax, zac, ceh, mac, kankin, muan, pax, koyab, cumhu。这些月份中的日期用0到19表示;Haab历的最后一个月叫做uayet,它只有5天,用0到4表示。玛雅人认为这个日期最少的月份是不吉利的:在这个月,法庭不开庭,人们不从事交易,甚至不打扫房屋。
因为宗教的原因,玛雅人还使用了另一个历法,这个历法中年被称为Tzolkin历法(holly年),一年被分成13个不同的时期,每个时期有20天,每一天用一个数字和一个单词相组合的形式来表示。使用的数字是1~13,使用的单词共有20个,它们分别是:imix, ik,akbal, kan, chicchan, cimi, manik, lamat, muluk, ok, chuen, eb, ben, ix,mem, cib, caban, eznab, canac, ahau。 注意:年中的每一天都有着明确唯一的描述,比如,在一年的开始,日期如下描述: 1 imix,2 ik, 3 akbal, 4 kan, 5 chicchan, 6 cimi, 7 manik, 8 lamat, 9 muluk, 10ok, 11 chuen, 12 eb, 13 ben, 1 ix, 2 mem, 3 cib, 4 caban, 5 eznab, 6canac, 7 ahau, 8 imix, 9 ik, 10 akbal ……也就是说数字和单词各自独
立循环使用。
Haab历和Tzolkin历中的年都用数字0,1,……表示,数字0表示世界的开始。所以第一天被表示成:
• Haab: 0. pop 0
• Tzolkin: 1 imix 0
请您帮助M. A. Ya教授,编写一个程序,把Haab历转化成Tzolkin历。

输入

• Haab历中的数据由如下的方式表示:
• NumberOfTheDay. Month Year(日期. 月份 年数)
• 输入中的第一行表示要转化的Haab历日期的数据量。接下来的每一行
表示一个日期,年数小于5000。

输出

• Tzolkin历中的数据由如下的方式表示:
• Number NameOfTheDay Year(天数字 天名称 年数)
• 第一行表示输出的日期数量。下面的每一行表示一个输入数据中对应的Tzolkin历中的日期。

解题思路

求出haab纪年法下天数总和,然后转换为tzolkin纪年法即可。
值得注意到是,haab纪念法是每个月是从0开始计数的。
先设定两个string函数haab和tzolin,用以完成月份名和月份数的转换,再设置一个结构体数组方便记录时间,最后计算天数和,转换成tzolkin输出。

源代码

#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
const int N = 5000;
struct data {
	int year,day;
	string month;
} p[N];
int n;
int main() {
	string haab[] = {"pop","no","zip","zotz","tzec",
	                 "xul","yoxkin","mol","chen","yax","zac","ceh",
	                 "mac","kankin","muan","pax","koyab","cumhu","uayet"
	                };
	string tzo[] = {"imix","ik","akbal","kan","chicchan","cimi",
	                "manik","lamat","muluk","ok","chuen","eb","ben","ix",
	                "mem","cib","caban","eznab","canac","ahau"
	               };
	cin>>n;
	cout<<n<<endl;
	for(int i = 1; i <= n; ++i) {
		scanf("%d. ",&p[i].day);
		cin>>p[i].month;
		cin>>p[i].year;
		int year,month,day,t,cnt;
		for(int j = 0; j<19; ++j) {
			if(p[i].month==haab[j]) {
				t = j;
				break;
			}
		}
		cnt = p[i].year*365+t*20+p[i].day;//计数共过了多少天
		year = cnt/260;// 按tzolki算经历了多少年
		cnt = cnt%260;//算出剩余总天数
		day =cnt%13+1;
		month = cnt%20;
		cout<<day<<" "<<tzo[month]<<" "<<year<<endl;
	}
	return 0;
}

B - Diplomatic License

问题重述

为了尽量减少外交开支,世界各国讨论如下。每一个国家最多只与一个国家保持外交关系是不够的,因为世界上有两个以上的国家,有些国家不能通过(一连串的)外交官进行相互交流。
• 本题设定每个国家最多与另外两个国家保持外交关系。平等对待每个国家是一条不成文的外交惯例。因此,每个国家都与另外两个国家保持外交关系。
• 国际地形学家提出一种适合这一需求的结构。他们将安排国家组成一个圈,使得每个国家都与其左右两个邻国建立外交关系。在现实世界中,一个国家的外交部是设在这个国家的首都。为了简单起见,本题设定,首都的位置是二维平面上的一个点。如果您用直线把保持外交关系的相关国家的外交部联
起来,结果就是一个多边形。
• 现在,要为两个国家之间的双边外交会议设定地点。同样,出于外交原因,两国的外交官前往该地点的距离必须相等。为了提高效率,应尽量缩短行驶距离,请您为双边外交会议做好准备。
• 输入
• 输入给出若干测试用例。每个测试用例首先给出数字n,表示涉及n个国家。本题设定n3是一个奇数。然后,给出n对x和y坐标,表示外交部的位置。外交部的坐标是绝对值小于1012的整数。国家的排列顺序与它们在输入中出现的顺序相同。此外,在列表中,第一个国家是最后一个国家的邻国。
• 输出
• 对于每个测试用例,首先输出测试用例中国家的数(=n),然后给出国家之间的双边外交会议地点位置的x和y坐标。输出的会议地点的顺序应与输入给出的顺序相同。从排在最前的两个国家的会议地点开始,一直到排在最后面的两个国家的会议地点,最后输出第n个国家和第一个国家的会议地点。

(简单的来说,计算相邻两个数的中点)

问题分析

按照以下思路:

  1. 定义结构体记录x,y坐标
  2. 设置一个结构体last,每当有新数就读进last。
  3. last和记录上一组数的结构体变量now计算平均值并输出
  4. now=last
    对于第一个数应当特殊处理,因为还要首末比较,所以设置了一个f结构体irst记录第一组数。

源代码:

#include<cstdio>
#include<iostream>
using namespace std;
struct point {
	long long int x;
	long long int y;
};
int main() {
	struct point now,first,last;
	int n=0;
	while(~scanf("%d",&n)){
		printf("%d ",n);
		cin >>first.x >>first.y;
		now=first;
		for(int i=1;i<n;i++)
		{
			cin >>last.x >>last.y ;
			printf("%.6f %.6f ",(last.x+now.x)/2.0,(last.y+now.y)/2.0);
			now=last;
		}
		now=first;
		printf("%.6f %.6f\n",(last.x+now.x)/2.0,(last.y+now.y)/2.0);
	}`在这里插入代码片`
	return 0;
	}

本题中我犯了以下错误
1.输出的形式是浮点数,我没有强制类型转换,也没有2加上小数点
2.x,y没有定义成long long型。

以下两题是指针的运用

C.“Accordian” Patience

问题重述

请您模拟"Accordian" Patience游戏,规则如下:
• 玩家将一副扑克牌一张一张地发牌,从左到右排成一排,不能重叠。只要一张扑克牌和左边的第一张牌或左边的第三张牌相匹配,就将这张扑克牌移被匹配的牌的上面。所谓两张牌匹配是这两张牌数值(数字或字母)相同或花色相同。每当移了一张牌之后,就再检查看这张牌能否继续往左移,每次只能移在牌堆顶部的牌。本游戏可以将两个牌堆变成一个牌堆,如果根据规则,可以将右侧牌堆的牌一张一张地移到左侧牌堆,就可以变成一个牌堆。本游戏尽可能地把牌往左边移动。如果最后只有一个牌堆,玩家就赢了。
• 在游戏过程中,玩家可能会遇上一次可以有多种选择的情况。当两张牌都可以被移动时,就移动最左边的牌。如果一张牌可以向左移动一个位置或向左移动三个位置,则将其移动三个位置。

输入

• 输入给出发牌的顺序。每个测试用例由一对行组成,每行给出26张牌,由单个空格字符分隔。输入文件的最后一行给出一个#作为其第一个字符。每张扑克牌用两个字符表示。第一个字符是面值(A=Ace,2-9,T=10,J=Jack,Q=Queen,K=King),第二个字符是花色(C= Clubs(梅花),D=Diamonds(方块),H=Hearts(红心),S=Spades(黑桃))。

输出

• 对于输入中的每一对行(一副扑克牌的52张牌),输出一行,给出在对应的输入行进行游戏后,每一堆扑克牌中剩余的扑克牌的数量。
这题我自己还没AC,跳过

D - Broken Keyboard

问题重述

您正在用一个坏键盘键入一个长文本。这个键盘的问题是时不时“Home”键或“End”键会在您输入文本时自动按下。您并没有意识到这个问题,因为你只关注文本,甚至没有打开显示器。完成键入后,您打开显示器,在屏幕上看到文本。在中文里,我们称之为悲剧。请您是找到悲剧的文本。

输入

• 输入给出若干测试用例。每个测试用例都是一行,包含至少一个,最多100,000个字母、下划线和两个特殊字符‘[’和‘]’;其中‘[’表示“Home”键,而‘]’表示“End”键。输入以EOF结束。

输出

• 对于每个测试用例,输出在屏幕上的悲剧的文本
Sample Input
This_is_a_[Beiju]_text
[[]][][]Happy_Birthday_to_Tsinghua_University
Sample Output
BeijuThis_is_a__text
Happy_Birthday_to_Tsinghua_University

这题同样没有ac,不评价,跳过

E - Satellites

问题重述

在这里插入图片描述

输入

• 输入包含一个或多个测试用例。
• 每个测试用例一行,给出两个整数s和a,以及一个字符串”min”或”deg”;其中s是人造卫星与地球表面的距离,a是这两颗人造卫星对地球中心的夹角。以分(′),或者以度(◦),为单位。输入不会既给出分,又给出度。

输出

• 对于每个测试用例,输出一行,给出两个卫星之间的圆弧距离和直线弦距离,以公里为单位。距离是一个浮点数,保存小数点后的六位数字。

问题分析

数学计算类问题需要弄明白题目,列出公式
在这里插入图片描述
可以用360°相减来处理超过180°的角

#include<iostream>
#include<cmath>
using namespace std;
double s,a;
string op;
//acos(-1)表示Π
int main() {
	while(cin >> s >> a >> op) {
		if(op == "min") a /= 60;
		if(a > 180) a = 360 - a;
		double arcdist = 2*acos(-1)*(s+6440.0)*a/360;
		double chord_dist = (s + 6440.0)*sin(a*acos(-1)/360)*2;
		printf("%.6lf %.6lf\n",arcdist,chord_dist);
	}
	return 0;
}

G - The Circumference of the Circle

问题重述

•要计算圆的周长似乎是一件容易的事,只要您知道圆的直径。但是,如果您不知道呢?给出平面上的3个非共线点的笛卡尔坐标。你的工作是计算与这3个点相交的唯一的圆的周长。

输入

• 输入包含一个或多个测试用例,每个测试用例一行,包含6个实数x1, y1, x2, y2, x3, y3,表示3个点的坐标。由这3个点确定的直径不超过1百万。输入以文件结束终止。

输出

• 对每个测试用例,输出一行,给出一个实数,表示3个点所确定圆的周长。输出的周长精确到小数两位。Pi的值为3.141592653589793。

问题分析

海伦公式,我滴神
在这里插入图片描述

源代码

#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
double xa,ya,xb,yb,xc,yc,p;
double getDistance(double x,double y,double xx,double yy) {
	return sqrt(pow(x-xx,2)+pow(y-yy,2));
}
int main() {
	while(cin >> xa >> ya >> xb >> yb >> xc >> yc) {
		double a = getDistance(xa,ya,xb,yb);
		double b = getDistance(xb,yb,xc,yc);
		double c = getDistance(xa,ya,xc,yc);
		double p = (a+b+c)/2;
		double s = sqrt(p*(p-a)*(p-b)*(p-c));
		double d = a*b*c/2.0/s;
		printf("%.2f\n",d*acos(-1.0));
	}
	return 0;
}

总结

本人对于链表的掌握不足,运用不足,并且不熟悉c的常用函数库与函数,应当改进

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值