HDU 4726 Kia's Calculation
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2436 Accepted Submission(s): 501
Problem Description
Doctor Ghee is teaching Kia how to calculate the sum of two integers. But Kia is so careless and alway forget to carry a number when the sum of two digits exceeds 9. For example, when she calculates 4567+5789, she will get 9246, and for 1234+9876, she will get 0. Ghee is angry about this, and makes a hard problem for her to solve:
Now Kia has two integers A and B, she can shuffle the digits in each number as she like, but leading zeros are not allowed. That is to say, for A = 11024, she can rearrange the number as 10124, or 41102, or many other, but 02411 is not allowed.
After she shuffles A and B, she will add them together, in her own way. And what will be the maximum possible sum of A "+" B ?
Input
The rst line has a number T (T <= 25) , indicating the number of test cases.
For each test case there are two lines. First line has the number A, and the second line has the number B.
Both A and B will have same number of digits, which is no larger than 106, and without leading zeros.
Output
For test case X, output "Case #X: " first, then output the maximum possible sum without leading zeros.
Sample Input
1
5958
3036
Sample Output
Case #1: 8984
【思路分析】
题意是给你两个长度相同且位数不超过106的整数,你需要分别先对这两个数进行数位之间的交换,但是交换后的数不能有前导零,然后你把这两个数按位相加(再余10),求这些情况中得到的最大的数。
一开始以为这两个数字的大小不超过106,错了很多次,最后注意到which is no larger than 106 ,这个is对应的是number of digits。。。。。。
要求满足题意的最大值,必定会涉及到两层for循环,若是直接对两个数a,b进行操作,则肯定会超时,但是改为对0—9这十个数字进行操作(若这个数字不存在a或b中则continue)就可以大大降低循环次数。求值的时候用到贪心的思想,即不断寻找当前数字和的最大值,但我个人觉得这个题目核心的地方还是在降低循环次数的操作上。
代码如下
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 1000010;
int first[15],second[15];
char s1[maxn],s2[maxn],ans[maxn];
int main()
{
int t;
scanf("%d",&t);
for(int i = 1;i <= t;i++)
{
scanf("%s %s",s1,s2);
printf("Case #%d: ",i);
int len = strlen(s1);
memset(first,0,sizeof(first));
memset(second,0,sizeof(second));
if(strcmp(s1,"0") == 0)
{
printf("%s\n",s2);
continue;
}
if(strcmp(s2,"0") == 0)
{
printf("%s\n",s1);
continue;
}
for(int j = 0;j < len;j++)//记录每个数字出现的次数
{
first[s1[j] - '0']++;
second[s2[j] - '0']++;
}
int num = 0,Max = -1,a,b;
for(int j = 1;j <= 9;j++)//找第一个数字(注意不能有前导零,所以j初值为1)
{
if(first[j] == 0)//j这个数字不存在
continue;
for(int k = 1;k <= 9;k++)
{
if(second[k] == 0)
continue;
int temp = (j + k) % 10;
if(temp > Max)
{
Max = temp;
a = j;
b = k;
}
}
}
ans[++num] = Max + '0';
first[a]--;
second[b]--;//取出后自减1
while(num < len)//找第二个及之后的数字
{
Max = -1;
for(int j = 0;j <= 9;j++)
{
if(first[j] == 0)
continue;
for(int k = 0;k <= 9;k++)
{
if(second[k] == 0)
continue;
int temp = (j + k) % 10;
if(temp > Max)
{
Max = temp;
a = j;
b = k;
}
}
}
ans[++num] = Max + '0';
first[a]--;
second[b]--;
}
int j;
for(j = 1;j <= len;j++)
{
if(ans[j] != '0')//忽视前导零
break;
}
if(j == len + 1)
printf("0\n");//结果的数位全为0情况直接输出零
else
{
for(;j <= len;j++)
{
printf("%c",ans[j]);
}
printf("\n");
}
}
return 0;
}