题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5920
题意:将一个数字分成不超过50个回文数字,只要不超过50个就行,不一定要最小。
思路:一道算是比较简单的题被我越搞越复杂。从中间开始向两边遍历并逐位赋值给b,找到不对称的地方时取较小的数,每次找到的b都是小于a的较大回文数字。如a = 123345,则第一个回文数字b = 123321; a = 12223 , b = 12221,;a = 32221,b = 12221,具体见注释吧。
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
char a[N],b[N],c[N],ans[N][N];
int main()
{
int T,cas = 1;
scanf("%d",&T);
while(T--)
{
scanf("%s",a);
int num = 0,len = strlen(a);
while(len >= 1)
{
//获取回文数字b
int flag = 0;
b[len >> 1] = a[len >> 1];
for(int i = len / 2 - 1; i >= 0; i--)
{
if(a[i] != a[len - 1 - i] && !flag)//第一次找到不对称的地方
{
flag = 1;
b[i] = b[len - 1 - i] = min(a[i],a[len - 1 - i]);
}
else
b[i] = b[len - 1 - i] = a[i];
}
b[len] = 0;
//特判
if(!flag)//a已经是回文串
{
strcpy(ans[num++],a);
break;
}
if(b[0] == '0')//特判
{
if(a[0] == '1')//分成1和999999.....
{
b[0] = '1',b[1] = 0;
strcpy(ans[num++],b);
for(int i = 0; i < len - 1; i++)
b[i] = '9';
b[len - 1] = 0;
strcpy(ans[num++],b);
}
else//分成9+199..991,8 + 299..992,7 + 399..993等
{
b[0] = b[len - 1] = (char)(a[0] - 1);
for(int i = 1; i < len - 1; i++)
b[i] = '9';
b[len] = 0;
strcpy(ans[num++],b);
int t6 = 11 - (int)(a[0] - '0');
b[0] = (char)(t6 + '0');
b[1] = 0;
strcpy(ans[num++],b);
}
if((len & 1) && (a[len >> 1] != '0'))//奇数位中间位置可能不为0,需要再次计算
{
strcpy(a,a + len/2);
len = (len + 1) >> 1;
continue;
}
break;
}
// 获取c,c = a - b
int t4 = 0;
for(int i = len - 1; i >= 0; i--)
{
int t1 = a[i] - '0', t2 = b[i] - '0';
int t3 = (t1 - t2 - t4 + 10) % 10;
c[i] = (char)(t3 + '0');
t4 = (int)((a[i] - b[i] - t4) < 0);
}
c[len] = 0;
//清除c的前导零
int t5;
for(int i = 0; i < len; i++)
{
if(c[i] != '0')
{
t5 = i;
break;
}
}
strcpy(ans[num++],b);
strcpy(a,c + t5);//将c赋值给a继续下一次循环
len = strlen(a);
}
printf("Case #%d:\n",cas++);
printf("%d\n",num);
for(int i = 0; i < num; i++)
printf("%s\n",ans[i]);
}
return 0;
}