c++算法练习

c++算法练习,第1张

c++算法练习

问题描述

题目描述
若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。
例如:给定一个十进制数 56,将 56 加 65(即把 5656 从右向左读),得到 121 是一个回文数。
又如:对于十进制数 87:
STEP1:87+78=165
STEP2:165+561=726
STEP3:726+627=1353
STEP4:1353+3531=4884
在这里的一步是指进行了一次 N 进制的加法,上例最少用了 4步得到回文数 4884。
写一个程序,给定一个 N(2≤N≤10 或N=16)进制数 M(100 位之内),求最少经过几步可以得到回文数。如果在 30 步以内(包含 30 步)不可能得到回文数,则输出 Impossible!。
输入格式
两行,分别是 N,M。
输出格式
如果能在 30 步以内得到回文数,输出格式形如 STEP=ans,其中 ans 为最少得到回文数的步数。
否则输出 Impossible!。
输入输出样例
输入
10
87
输出 
STEP=4

解题思路

本问题需要解决的是要求输入数字与其逆序排列的数字相加在30次内可以得到一个对称的数字(回文数),判断输入数字以及相加时候的数字是否为回文数,进行N进制的数据的加减(本身利用各个进制的加法实现),通过递归实现string和int字符的转换来辅助加减,记录递归的次数,并判断在30次内是否可以实现;

解题方案

用string字符存储输入数据M,通过递归形式实现string和int之间的转换,没有很好的解决N进制问题,单纯利用进制加减过于复杂

源代码

#include
#include
#include
#include
using namespace std;
//老师,剩下进制的加法运算好复杂,我只实现了二进制和十进制,其他的也能实现就是很复杂
// 是不是我的思路错了,应该有更简洁的算法吧
//string转换成int
int inreverse(string str)
{
	int n;
	stringstream stream;
	stream << str;
	stream >> n;
	return n;
}
//int转换为string
string streverse(int n)
{
	string str;
	stringstream stream;
	stream << n;
	stream >> str;
	return str;
}
//判断是否为回文数
int isrecycle(string str)
{
	string str1 = str;
	reverse(str1.begin(), str1.end());
	if (str.compare(str1)==0)
	{
		return 0;   //两字符相等;
	}
	else
		return 1;  //不是回文数;
}
//二进制加法
int add2(int a, int b) 
{
	int re = a;
	while (b) {
		int tmp = a;
		a = a ^ b;
		b = (tmp & b) << 1;
		re = a;
	}
	return re;
}
//回文数算法
int elem10(string str, int &step,int m)
{
	int s = inreverse(str);
	reverse(str.begin(), str.end());
	int d = inreverse(str);
	int n = 0;
	switch (m)
	{
	case 10:
		n = s + d;
		break;
	case 2:
		n = add2(s, d);
		break;
	default:
		break;
	}
	string s2 = streverse(n);
	//cout << s2 << endl;
	if (int ret = isrecycle(s2) == 0)
	{
		return step + 1;
	}
	else
	{
		elem10(s2, step,m);
		step++;
	}
	return step+1;
}
int main()
{
	int a;
	string s;
	int step = 0;
	cout << "请输入几进制数N(N=2,8,16,10):" << endl;
	cin >> a;
	cout << "请输入进制数M:" << endl;
	cin >> s;
	if (int ret = isrecycle(s) == 0)
	{
		cout << "step=" << step << endl;
	}
	else
	{
		cout << "step=" << elem10(s, step, a) << endl;
	}
	return 0;
}

解题正解 

主要优化了N进制计算上

  

#include
#include
#include
#include

using namespace std;

int n,ans;
string str;
vector s1,s2;

int main()
{
	cin>>n;
	cin>>str;
	for(int i=0;i='0'&&str[i]<='9')
			s1.push_back(str[i]-'0');
		else
			if(str[i]>='A')				//十六进制需注意字母大小写 
				s1.push_back(str[i]-'A'+10);
			else
				s1.push_back(str[i]-'a'+10);
	}
	s2=s1;
	reverse(s1.begin(),s1.end());		//反转函数 
	if(s1==s2)
	{
		cout<<"STEP=0";
		return 0;
	}
	while(++ans<=30)	//计数 
	{
		int len=s1.size();
		for(int i=0;i=n)	//某一位大于n时需进行进位 *** 作 
			{
				if(i!=len-1) s1[i+1]++;	//每次最多进1,这里由于两数互相倒序,向前进位与向后进位对本题无影响 
				else s1.push_back(1);	//当最后一位满n,进位需要多申请一个位置进位
			}
			s1[i]%=n;	//进位后留下余数 
		}
		s2=s1;
		reverse(s1.begin(),s1.end());
		if(s1==s2)
		{
			cout<<"STEP="<

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5702705.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存