C/C++程序题(26-30)

26.

副牌中发五张扑克牌给你:让你判断数字的组成:
 
有以下几种情况:
1:四条:即四张一样数值的牌(牌均不论花色)

2:三条带 一对

3:三条带两张不相同数值的牌

4:两对

5:顺子  包括 10,J,Q,K,A

6:什么都不是

 7:只有一对

#include<iostream>
using namespace std;


bool IS(char *str)//判断五个各异的数是否连号
{
	int n=strlen(str);
	char temp;
	for(int i=0;i<n;i++)
	{
		for (int j=i+1;i+j<n;j++)
		{
			if(str[j]<str[i])
			{
				temp=str[i];
				str[i]=str[j];
				str[j]=temp;
			}
		}
	}
	for(int i=0;i<n-1;i++)
	{
		if(str[i+1]!=str[i]+1) return false;
	}
	return true;

}
void main()
{
	char *str=new char[5];
	char *temp=new char[2];
	int n[5]={0,0,0,0,0};
	for(int i=0;i<5;i++)
	{
		cin>>temp;
		if(temp=="10") str[i]='I';
		else str[i]=temp[0];
	}
	for(int i=0;i<5;i++)//用每个数同整个5个数相比较,n[5]记录每个数的重复次数
	{                   //例如第一种情况数组里是4、4、4、4、1(数序不定)
		int num=0;      //第二种情况是3、3、3、2、2
		for(int j=0;j<5;j++)
		{
			if(str[i]==str[j]) num++;
		}
		n[i]=num;
	}
	for(int i=0;i<5;i++)
	{
		if(n[i]==4)
		{
			cout<<"1"<<endl;
			return;
		}
			
		if(n[i]==3)
		{
			for(int j=0;j<5;j++)
			{
				if(n[j]==2) 
				{
					cout<<"2"<<endl;
					return;
				}
				
				if(n[j]==1)
				{
					cout<<"3"<<endl;
					return;
				}
			}
		}
		if(n[i]==1)
		{
			int a=0;
			for(int j=0;j<5;j++)
			{
				if (n[j]==1) a++; 
			}
			if(a==3)
			{
				cout<<"7"<<endl;
				return;
			}
			if(a==1)
			{
				cout<<"4"<<endl;
				return;
			}
			if(a==5)
			{
				for(int j=0;j<5;j++)
				{
					if(str[j]=='I') str[j]='9'+1;
					if(str[j]=='J') str[j]='9'+2;
					if(str[j]=='Q') str[j]='9'+3;
					if(str[j]=='K') str[j]='9'+4;
					if(str[j]=='A') str[j]='9'+5;
				}
				if(IS(str))
				{
					cout<<"5"<<endl;
					return;
				}
				else
				{
					cout<<"6"<<endl;
					return;
				}

			}
		}
	}
}
注:这种算法思想是通过每个数相对应的重复次数例如

1,44441    2,33322    3,33311   4,22221   5,11111   6,11111   7,22111

其中第5、6种情况需判断是否是顺子

还一种算法是转化成整数数组,对数组排序后直接比较




27.高精度整数加工

 问题描述:
 
在计算机中,由于处理器位宽限制,只能处理有限精度的十进制整数加减法,比如在32位宽处理器计算机中,
 参与运算的操作数和结果必须在-231~231-1之间。如果需要进行更大范围的十进制整数加法,需要使用特殊
 的方式实现,比如使用字符串保存操作数和结果,采取逐位运算的方式。如下:
9876543210 + 1234567890 = ?
让字符串 num1="9876543210",字符串 num2="1234567890",结果保存在字符串 result= "11111111100"。
-9876543210 + (-1234567890) = ?
让字符串 num1="-9876543210",字符串 num2="-1234567890",结果保存在字符串result = "-11111111100"。
 要求编程实现上述高精度的十进制加法。
 要求实现函数:
 void add (const char *num1, const char*num2, char *result)
 【输入】num1:字符串形式操作数1,如果操作数为负,则num1[0]为符号位'-'
 num2:字符串形式操作数2,如果操作数为负,则num2[0]为符号位'-'
 【输出】result:保存加法计算结果字符串,如果结果为负,则result[0]为符号位。
 注:
I、   当输入为正数时,'+'不会出现在输入字符串中;当输入为负数时,'-'会出现在输入字符串中,且一定在输入字符串最左边位置;
 II、  输入字符串所有位均代表有效数字,即不存在由'0'开始的输入字符串,比如"0012", "-0012"不会出现;
 III、       要求输出字符串所有位均为有效数字,结果为正或0时'+'不出现在输出字符串,结果为负时输出字符串最左边位置为'-'。

#include <iostream>
using namespace std;


void add(const char* num1,const char* num2,char* result)
{
	int n1=strlen(num1);
	int n2=strlen(num2);
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	if(num1[0]=='-'&&num2[0]=='-')//两个都是负数
	{
		result[0]='-';
		int temp=0;
		if(n1<n2) swap(num1,num2);
		n1=strlen(num1);
	    n2=strlen(num2);
		for(int i=1;i<n2;i++)
		{
			int m1=num1[n1-i]-'0';
			int m2=num2[n2-i]-'0';
			int m=m1+m2+temp;
            temp=m/10;
			result[n1-i+1]=m%10+'0';

		}
		for(int i=n2;i<n1;i++)
		{
			int m1=num1[n1-i]-'0';
			int m=m1+temp;
			temp=m/10;
			result[n1-i+1]=m%10+'0';
		}
		result[1]=temp+'0';
		result[n1+1]='\0';
	}
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	else if(num1[0]=='-'||num2[0]=='-')//一正一负 ****重点减法借位的实现
	{
		if(num1[0]=='-')
			swap(num1,num2);
		n1=strlen(num1);
		n2=strlen(num2)-1;

		int judge;//判断绝对值的大小1、2、3分别表示n1大于n2、小于、等于
		if(n1>n2)
			judge=1;
		else
		{
			if(n1<n2) judge=2;
			else 
			{
				for(int i=0;i<n1;i++)
				{
					if(num1[i]>num2[i+1])
					{
						judge=1;
						break;
					}
					else if(num1[i]<num2[i+1])
					{
						judge=2;
						break;
					}
					judge=3;
				}
			}
		}

		n2=strlen(num2);

		if(judge==1)//正数的绝对值大于负数时,运算分为两部分
		{
			int temp=0;//表示是否向上借位
			for(int i=1;i<n2;i++)//第一部分
			{
				if(temp==1&&num1[n1-i]=='0')//从0借位时
				{
					result[n1-i]=num1[n1-i]+10-temp-num2[n2-i]+'0';
					temp=1;
				}
				else
				{
				  if(num1[n1-i]-temp>=num2[n2-i])
				  {
					  result[n1-i]=num1[n1-i]-temp-num2[n2-i]+'0';
					  temp=0;
				  }
					
				  else
				  {
					  result[n1-i]=num1[n1-i]-temp+10-num2[n2-i]+'0';
				  	  temp=1;
				  }
				}
			}
			for(int i=n2;i<=n1;i++)//第二部分 可视为短的字符串前面补零,num1与0相减
			{
				if(temp==1&&num1[n1-i]=='0')
				{
					result[n1-i]=num1[n1-i]+10-temp;
					temp=1;
				}
				else
				{
					result[n1-i]=num1[n1-i]-temp;
					temp=0;
				}
			}
			result[n1]='\0';
		}

		if(judge==2)//正数绝对值小于负数时,同上
		{
			int temp=0;
			for(int i=1;i<=n1;i++)
			{
				if(temp==1&&num2[n2-i]=='0')
				{
						result[n2-i]=num2[n2-i]-num1[n1-i]+10-temp+'0';
					    temp=1;
				}
				else
				{
					if(num2[n2-i]-temp>=num1[n1-i])
					     result[n2-i]=num2[n2-i]-temp-num1[n1-i]+'0';
				    else
				    {
					    result[n2-i]=num2[n2-i]-num1[n1-i]+10-temp+'0';
					    temp=1;
				    }

				}

			}
			for(int i=n1+1;i<=n2;i++)
			{
				if(temp==1&&num2[n2-i]=='0')
				{
					result[n2-i]=num2[n2-i]+10-temp;
					temp=1;
				}
				else
				{
					result[n2-i]=num2[n2-i]-temp;
					temp=0;
				}

			}
			result[n2]='\0';
		}
		if(judge==3)
		{
			result[0]='0';
			result[1]='\0';
		}

	}
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	else           //都是正数
	{
		int temp=0;
		if(n1<n2) swap(num1,num2);
		n1=strlen(num1);
	    n2=strlen(num2);
		for(int i=1;i<=n2;i++)
		{
			int m1=num1[n1-i]-'0';
			int m2=num2[n2-i]-'0';
			int m=m1+m2+temp;
            temp=m/10;
			result[n1-i+1]=m%10+'0';

		}
		for(int i=n2;i<=n1;i++)
		{
			int m1=num1[n1-i]-'0';
			int m=m1+temp;
			temp=m/10;
			result[n1-i+1]=m%10+'0';
		}
		result[0]=temp+'0';
		result[n1+1]='\0';
	}

	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	//去除结果前面的无效0
	if(result[0]=='-')
	{
		int n=strlen(result);
		while(result[1]=='0')
		{
			for(int i=2;i<n+1;i++)
			{
				result[i-1]=result[i];
			}
		}
	}
	else
	{
		int n=strlen(result);
		while(result[0]=='0')
		{
			for(int i=1;i<n+1;i++)
				result[i-1]=result[i];
		}
	}
}
void main()
{
	char* num1=new char[100];
	char* num2=new char[100];
	char* result=new char[100];
	cin>>num1>>num2;
	add(num1,num2,result);
	int r=strlen(result);
	for(int i=0;i<r;i++)
	cout<<result[i];
	
}

注:其中关键点是相同符号的相加进位运算和不同号的减法借位运算,特别注意从0借位



28.

单词迷宫

题目简介:
Word Maze
是一个网络小游戏,你需要找到以字母标注的食物,但要求以给定单词字母的顺序吃掉。假设给定单词if,你必须先吃掉i然后才能吃掉f。但现在你的任务可没有这么简单,你现在处于一个mí宫Maze(n×m的矩阵)当中,里面到处都是以字母标注的食物,但你只能吃掉能连成给定单词W的食物。
如下图,指定W为“SOLO”,则在地图中红色标注了单词“SOLO”。
注意区分英文字母大小写,你只能上下左右行走。
运行时间限制:  无限制
内存限制:  无限制
输入:
输入第一行包含两个整数n、m(0<n, m<21)分别表示n行m列的矩阵,第二行是长度不超过100的单词W,从第3行到底n+3行是只包含大小写英文字母的长度为m的字符串。
输出:
如果能在地图中连成给定的单词,则输出“YES”,否则输出“NO”。注意:每个字母只能用一次。
样例输入:
5 5
SOLO
CPUCY
EKLQH
CRSOL
EKLQO
PGRBC
样例输出:yes



#include<iostream>
using namespace std;

int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
bool IS(int r1,int c1,char maze[100][100],char *str,int *visit,int n,int row,int col)
{
	if(n==strlen(str)) return true;
	else
	{
	    for(int j=0;j<4;j++)
	    {
		    r1+=dir[j][0];
		    c1+=dir[j][1];
		    if(r1>=0&&r1<row&&c1>=0&&c1<col)
		    {
			   if(str[n]==maze[r1][c1]&&!visit[r1*row+c1])
			   {
				   n++;
				   visit[r1*row+c1]=1;
				   return IS(r1,c1,maze,str,visit,n,row,col);
			   }
		    }

	    }
		return false;
	}
}
void main()
{
	int row,col;
	cin>>row>>col;
	char maze[100][100];
	char* str=new char[100];
	cin>>str;
	for(int i=0;i<row;i++)
		for(int j=0;j<col;j++)
			cin>>maze[i][j];

	int pos[10];
	int t=0,m=0;
	for(int i=0;i<row;i++)
		for(int j=0;j<col;j++)
		{
			m++;
			if(maze[i][j]==str[0])
				pos[t++]=m;//找出所有's'的位置
		}
	int visit[100]={0};
	//memset(visit,0,sizeof(100));
	bool b;
	for(int i=0;i<t+1;i++)//分析每一个s
	{
		int r=pos[i]/row;
		int c=pos[i]%col;
		int n=1;
		b=IS(r,c,maze,str,visit,n,row ,col);
		if(b==true)
		{
			cout<<"YES"<<endl;
			return;
		}
		memset(visit,0,sizeof(row*col));//每换一个s将访问标记重置
	}
	cout<<"NO"<<endl;
	delete  []str;
}

注:在连续字母的寻找过程中,用递归函数来实现。例"solo",先寻找s的邻接点是否有o,再寻找o的邻接点是否有l,以此类推。<只适用四个邻接点只存在一个符合点的情况,不严谨!>


29.

描述:10个学生考完期末考试评卷完成后,A老师需要划出及格线,要求如下:
(1) 及格线是10的倍数;
(2) 保证至少有60%的学生及格;
(3) 如果所有的学生都高于60分,则及格线为60分
输入:输入10个整数,取值0~100
输出:输出及格线,10的倍数
输入样例:61 51 49 3020 10 70 80 90 99
输出样例:50

#include <iostream>
using namespace std;

void main()
{
	int grade[10];
	int pass;
	int n=0,m=0;
	for(int i=0;i<10;i++)
	{
		cin>>grade[i];
		if(grade[i]>=60)
		n++;//统计过60的人
	}
	if(n==10)//全过60
		pass=60;
	else
	{
		for(int i=0;i<10;i++)
		{
			m=0;
			pass=(10-i)*10;//从100逐次减10
			for(int j=0;j<10;j++)
			{
				if(grade[j]>=pass)
					m++;
			}
			if(m>=6) break;
		}
	}
	cout<<pass<<endl;

}



30.

一条长廊里依次装有n(1 ≤ n ≤ 65535)盏电灯,从头到尾编号1、2、3、…n-1、n。每盏电灯由一个拉线开关控制。开始,电灯全部关着。
有n个学生从长廊穿过。第一个学生把号码凡是1的倍数的电灯的开关拉一下;接着第二个学生把号码凡是2的倍数的电灯的开关拉一下;接着第三个学生把号码凡是3的倍数的电灯的开关拉一下;如此继续下去,最后第n个学生把号码凡是n的倍数的电灯的开关拉一下。n个学生按此规定走完后,长廊里电灯有几盏亮着。
注:电灯数和学生数一致。

输入:65535

输出:255

#include <iostream>
using namespace std;

void main()
{
	int num,n=0;
	cin>>num;
	for(int i=1;i<=num;i++)
	{
		int m=0;//每盏灯因数的个数
		for(int j=1;j<=i;j++)
		{
			if(i%j==0) m++;
		}
		if(m%2==1) n++;//如果因数为奇数则为亮灯
	}
	cout<<n<<endl;
}

注: 一盏灯的开关被按的次数,恰等于这盏灯的编号的因数的个数;对于任何一盏灯,由于它原来不亮,那么当它的开关被按奇数次时,灯是开着的.双循环耗时很长,如果有时间限制的话,不建议采用这种直白的方法.

每个数除以一个数A等于另一个数B,那么A和B都是它的因数,于是因数是成对出现的,但是要因数是奇数,就必须A=B所以这个数就必须是一个是的平方得到的,即完全平方数有奇数个因数.那么这道题可以转化为,就是寻找找1-65535中完全平方数的个数。

#include <iostream>
using namespace std;

void main()
{
	int num,n=0;
	cin>>num;
	for(int i=1;;i++)
	{
		if(i*i>num) break;
		n++;
	}
	cout<<n<<endl;
}
如果循环改为

for(int i=1;i<num;i++)
if(i*i<=num) n++;

则会出错.因为整型过大,int类型溢出.

整型数据范围:

unsigned   int   0~4294967295   
int   -2147483648~2147483647                       4byte =  32 bit
unsigned long 0~4294967295
long   -2147483648~2147483647                     4byte =  32 bit 

long long的最大值:9223372036854775807
long long的最小值:-9223372036854775808
unsigned long long的最大值:1844674407370955161

__int64的最大值:9223372036854775807
__int64的最小值:-9223372036854775808
unsigned __int64的最大值:18446744073709551615








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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值