《算法笔记》学习笔记:3.1简单模拟(codeup)

学算法笔记的题解记录:

3_1简单模拟题

  1. List item
  2. A. 剩下的树
  3. B. A+B
  4. C. 特殊乘法
  5. D. 比较奇偶个数
  6. E. Shorest Distance
  7. F. A+B和C
  8. G. 数字分类
  9. H. 部分A+B
  10. I. 锤子剪刀布

问题 A: 剩下的树

题目描述
有一个长度为整数L(1<=L<=10000)的马路,可以想象成数轴上长度为L的一个线段,起点是坐标原点,在每个整数坐标点有一棵树,即在0,1,2,…,L共L+1个位置上有L+1棵树。
现在要移走一些树,移走的树的区间用一对数字表示,如 100 200表示移走从100到200之间(包括端点)所有的树。
可能有M(1<=M<=100)个区间,区间之间可能有重叠。现在要求移走所有区间的树之后剩下的树的个数。

这个题目,最开始我是想通过设置一个数组,所有的数都设置为零,在移走区间里面的数设置为1。最后再遍历一下数组,统计为零的数有多少,然后一想,设置一个统计移走树数量的变量,在设置数为1时,将其加1,最后用总的树去减就是剩余树的数量,所以代码如下

#include<stdio.h>
#include<string.h>

int main()
{
	int l,m;
	while(scanf("%d%d",&l,&m) != EOF){
		if(l==0 && m==0) break;					//需要注意输入数据,根据两个数都为零为结束标志。
		int a[l+1],sum=0;						//便于输入的数据之间使用
		memset(a,0,sizeof(a));
		while(m--){
			int x,y;							//表示移走树的区间长度
			scanf("%d%d",&x,&y);
			for(;x<=y;x++){
				if(a[x]!=1){					//若该处还有树
					a[x] = 1;
					sum++;
				}
			}
		}
		printf("%d\n",l-sum+1);
	}
	return 0;
}

问题 B: A+B

题目描述 给定两个整数A和B,其表示形式是:从个位开始,每三位数用逗号","隔开。 现在请计算A+B的结果,并以正常形式输出。

输入 输入包含多组数据数据,每组数据占一行,由两个整数A和B组成(-10^9 < A,B < 10^9)。

输出 请计算A+B的结果,并以正常形式输出,每组数据占一行。

样例输入
-234,567,890 123,456,789
1,234 2,345,678
样例输出
-111111101 2346912

输入数据有’,’ 所以将以字符串str1的形式接受,然后将该字符串数字和符号信息复制到另一字符数组str2中(类似于删除所有的逗号),再通过sscanf(str2,"%d",&a);将其转化为所需的数据,之后相加得到数据输出。

//3_1 B A+B 
#include<stdio.h>
#include<string.h>

int main()
{
	int change(char s[]);			//转化函数,将输入的数据转化为整数。
	char a[20],b[20];
	while(scanf("%s %s",a,b)!=EOF){
		int num1,num2;
		num1 = change(a);
		num2 = change(b);
		printf("%d\n",num1+num2);
	}
	return 0;
}

int change(char s[]){
	int num,n,i,j;
	char s1[20];
	n = strlen(s);
	for(i=0,j=0;i<n;i++){
		if((s[i]>='0' && s[i]<='9')|| s[i]=='-'){
			s1[j++] = s[i];
		}
	}
	s1[j] = '\0';
	sscanf(s1,"%d",&num);
	return num;
	
}

问题 C: 特殊乘法

题目描述 写个算法,对2个小于1000000000的输入,求结果。特殊乘法举例:123 * 45 = 14 +15 +24 +25+34+35 输入 两个小于1000000000的数

输出 输入可能有多组数据,对于每一组数据,输出Input中的两个数按照题目要求的方法进行运算后得到的结果。

样例输入
24 65
42 66666
3 67
样例输出 66 180 39

将每个数都转化一个数组,数组的元素为数中的每一位,之后两个数组中的元素逐一相乘,累加后得到正确答案。

#include<stdio.h>

int main()
{
	int convert(int s[],int num);	//将数中的每一位赋值给数组中的相应位置,并返回数的位数。
	int a[20],b[20];
	int num1,num2;					// 分别记录两个数组的使用长度,即数的位数,方便使用。
	while(scanf("%d%d",&num1,&num2) != EOF){
		int n1 = convert(a,num1);
		int n2 = convert(b,num2);
		int i,j,sum=0;
		for(i=0;i<n1;i++){
			for(j=0;j<n2;j++){
				sum += a[i]*b[j];
			}
		}
		printf("%d\n",sum);
	}
}

int convert(int s[],int num){
	int n=0;
	while(num!=0){
		s[n++] = num%10;
		num /= 10;
	}
	return n;
}

问题 D: 比较奇偶数个数

题目描述 第一行输入一个数,为n,第二行输入n个数,这n个数中,如果偶数比奇数多,输出NO,否则输出YES。 按照题意编写即可,代码如下

// 3_1 D 比较奇偶个数
#include<stdio.h>
int main()
{
	int n;
	while(scanf("%d",&n) != EOF){
		int a,p=0,o=0;					//p表示偶数,o表示奇数 
		while(n--){
			scanf("%d",&a);
			if(a%2==0){
				p++;
			}else o++;
		}
		if(p>o){
			printf("NO\n");
		} else printf("YES\n");
	}
	return 0; 
 } 

问题 E: Shortest Distance (20)

题目描述
The task is really simple: given N exits on a highway which forms a simple cycle, you are supposed to tell the shortest distance between any pair of exits

因为是循环数组,所以把所有路径的总长度求出来,再设置一个数组存放任一个点到起始点的位置(提前设置,防止每次使用都要重新遍历,导致时间超出),每输入一个数的时候就进行求出,两点之间的两个距离,进行比较,然后输出。代码如下

//A1046 Shortest Distance 
#include<stdio.h>
/*既然是循环队列,所以可能是顺序到达,也可能是逆序到达。
所以每次都遍历整个数组,在范围内的加起来,不在的也加起来 ,取最小值*/ 
int main()
{
	int n,n1;
	scanf("%d",&n);
	int x[n+1],dis[n+1],i,sum=0;			// x[i]存放循环数组,dis数组防止到每个点的距离,sum为循环链总长度
	for(i=1;i<=n;i++){
		scanf("%d",&x[i]);
        sum += x[i];
        dis[i] = sum;
	}
	
	scanf("%d",&n1);
	while(n1--){		
		int left,right;
		int sum1=0,sum2=0;
		scanf("%d%d",&left,&right);
		if(left>right){						//默认left 小于 right
			int t = left;
			left = right;
			right = t;
		}
		sum1 = dis[right-1] - dis[left-1];
        sum2 = sum-sum1;
		if(sum1>sum2){
			printf("%d\n",sum2);
		}else printf("%d\n",sum1);
	}
	return 0;
}

问题 F: A+B和C (15)

题目描述
给定区间[-231, 231]内的3个整数A、B和C,请判断A+B是否大于C。
按照题意写出代码即可,注意整数的取值范围,要用long

//3_1 F A+B和C
#include<stdio.h>
//注意数据范围,需要长整型 
int main()
{
	char *t = "true";
	char *f = "false",*q;
	int n,num=0;
	scanf("%d",&n);
	while(n--){
		long a,b,c;
		scanf("%ld%ld%ld",&a,&b,&c);
		if(a+b>c){
			q = t;
		}else q = f;
		num++;
		
		printf("Case #%d: %s\n",num,q);
	}
	return 0;
 } 

问题 G: 数字分类 (20)

题目描述
给定一系列正整数,请按要求对数字进行分类,并输出以下5个数字:

A1 = 能被5整除的数字中所有偶数的和;
A2 = 将被5除后余1的数字按给出顺序进行交错求和,即计算n1-n2+n3-n4…;
A3 = 被5除后余2的数字的个数;
A4 = 被5除后余3的数字的平均数,精确到小数点后1位;
A5 = 被5除后余4的数字中最大数字。

代码如下,想法是多分支结构,简单模拟,需要注意的是A1的数是偶数,需要再判断一下

//3_1 G 数字分类
#include<stdio.h> 
#include<string.h> 
int main()
{
	int n,i;
	while(scanf("%d",&n) != EOF){
		int a[2][5],m = 1,x;						// 二维数组,分别存放某种类别数量,和该种情况下的结果数 
		double avg = 0;								//接收A4的数据 
		memset(a,0,sizeof(a));
		while(n--){
			int index = 0;
			scanf("%d",&x);
			index = x%5;							// 根据余数来判断是那种类型 
			a[0][index]++;
			switch(index){
				case 0: 
					if(x%2==0){						//注意这里是要偶数 
						a[1][index] += x;
					}else a[0][index]--; 
					break;
				case 1: 
					a[1][index] += (x*m);
					m *= -1;
					break;
				case 2:
					a[1][index]++;
					break;
				case 3:
					avg += x;
					break;
				case 4:
					if(x>a[1][index]){
						a[1][index] = x;
					}
					break;
			}
		}
		for(i=0;i<5;i++){
			if(a[0][i]!=0){
				if(i != 3){						// 特殊情况特殊处理 
					printf("%d ",a[1][i]);
				}else printf("%.1f ",avg/a[0][i]);
			}else printf("N ");
		}
		printf("\n");
	}
	return 0;
} 

问题 H: 部分A+B (15)

题目描述
正整数A的“DA(为1位整数)部分”定义为由A中所有DA组成的新整数PA。例如:给定A = 3862767,DA = 6,则A的“6部分”PA是66,因为A中有2个6。

现给定A、DA、B、DB,请编写程序计算PA + PB。

输入
输入在一行中依次给出A、DA、B、DB,中间以空格分隔,其中0 < A, B < 1010。
输出
在一行中输出PA + PB的值。
样例输入
3862767 6 13530293 3
3862767 1 13530293 8
样例输出
399
0

按照题意将两个部分数求出来,再相加即可

//3_1 H 部分A+B
 #include<stdio.h>
 #include<string.h>
 int main(){
 	int new_p(int x,int dx);				// 将x中和dx一样的数,组成一个新的数 
 	int mul_n(int n,int x);					// 将x变为n个x组合,例如,x=3,n=2 返回的数为33 
 	int a,da,b,db;
 	while(scanf("%d%d%d%d",&a,&da,&b,&db) != EOF){
 		int pa,pb;
 		pa = new_p(a,da);
 		pb = new_p(b,db);
 		printf("%d\n",pa+pb);
	 }
	 return 0;
 }
 
int new_p(int x,int dx){// 将x中和dx一样的数,组成一个新的数 
	int a[10],num =0,i;
	memset(a,0,sizeof(a));
	while(x != 0){
		int	index = x%10;
		x /= 10;
		a[index]++;
	}
	for(i=0;i<10;i++){
		if(i==dx && a[i]!=0){
			num = mul_n(a[i],dx);
			break;
		}
	}
	return num;
	
}
int mul_n(int n,int x){	// 将x变为n个x组合,例如,x=3,n=2 返回的数为33 
	int m = 1,sum = 0;
	while(n--){
		sum += (m*x);
		m *= 10;
	} 
	return sum;
}

问题 I: 锤子剪刀布 (20)

题目描述
大家应该都会玩“锤子剪刀布”的游戏:两人同时给出手势,胜负规则如图所示:
现给出两人的交锋记录,请统计双方的胜、平、负次数,并且给出双方分别出什么手势的胜算最大。

这个我用了超级蠢的办法,不建议使用,代码如下

//3_1 I 锤子剪刀布
#include<stdio.h>
#include<string.h>
int main()
{
	int n ,win =0,loses=0,com=0,x[3],y[3],max1=0,max2=0;
	int i=0;
	char b1,b2;
	scanf("%d",&n);
	memset(x,0,sizeof(x));
	memset(y,0,sizeof(y));
	getchar();
	while(n--){
		char a,b;
		scanf("%c %c",&a,&b);
	//	printf("%c 1111 %c\n",a,b);
		getchar();
		switch(a){
			case 'B':
				switch(b){
					case 'B':com++;break;
					case 'C':win++;x[0]++;break;
					case 'J':loses++;y[2]++;break;
				}break;
			case 'C': 
				switch(b){
					case 'C': com++;break;
					case 'J': win++;x[1]++;break;
					case 'B': loses++;y[0]++;break;
				}break;
			case 'J':
				switch(b){
					case 'C':loses++;y[1]++;break;
					case 'J':com++;break;
					case 'B': win++;x[2]++;break;
				}break;
		}
	}
		for(i=0;i<3;i++){
			if(x[i]>x[max1]){
				max1 = i;
			}
			if(y[i]>y[max2]){
				max2 = i;
			}
		}
		printf("%d %d %d\n",win,com,loses);
		printf("%d %d %d\n",loses,com,win);
		switch(max1){
			case 0: b1='B';break;
			case 1: b1= 'C';break;
			case 2:b1= 'J';break;
		}
		switch(max2){
			case 0: b2= 'B';break;
			case 1: b2= 'C';break;
			case 2: b2 = 'J'; break;
		}
		printf("%c %c\n",b1,b2);
	return 0;
}

这个题另一种思路是找到其中的规律,用数组来表示其中的逻辑。
模拟的话,目前就这样吧。

发布了14 篇原创文章 · 获赞 8 · 访问量 234

猜你喜欢

转载自blog.csdn.net/weixin_43582715/article/details/102774003