免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 6535 | 回复: 27
打印 上一主题 下一主题

[算法] 算法求一个数a的下一个临近数b,详情如下 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-10-26 18:36 |只看该作者 |倒序浏览
求一个数a的下一个临近数b,满足如下条件:
1 b>a
2 a的各个位的数字之和等于b的各个位之和
3 b是满足1,2条件的最小数
比如
a=113则b=122
a=10  则b=100
a=200则b=1001
求通用的计算方法int fun(int a)
返回值为b
[不用蛮力法]

[ 本帖最后由 fertiland 于 2007-10-26 18:59 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2007-10-26 18:49 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
3 [报告]
发表于 2007-10-26 18:50 |只看该作者
原帖由 fertiland 于 2007-10-26 18:36 发表
求一个数a的下一个临近数b,满足如下条件:
1 b>a
2 a的各个位的数字之和等于b的各个位之和
3 b是满足1,2条件的最小数
比如
a=113则b=122
a=10  则b=100
a=200则b=1001
求通用的计算方法int fun(int a)
...

写了一个, 也许还有效率更高的!

  1. #include<stdio.h>
  2. int count(int a)
  3. {
  4.         int i = 0;
  5.         do
  6.         {
  7.                 i += a % 10;
  8.         }while (a = a / 10);
  9.         return i;
  10. }

  11. int fun(int a)
  12. {
  13.         int i = count(a);
  14.         while (1)
  15.         {
  16.                 a++;
  17.                 if (count(a) == i)
  18.                         return a;
  19.         }
  20. }

  21. int main()
  22. {
  23.         int a;
  24.         int i;
  25.         scanf("%d", &a);
  26.         i = fun(a);
  27.         printf("out : %d\n", i);
  28.         return 0;
  29. }
复制代码

论坛徽章:
0
4 [报告]
发表于 2007-10-26 18:55 |只看该作者
怎么都想到的是蛮力法解?
谢谢,动作很快啊

[ 本帖最后由 fertiland 于 2007-10-26 18:59 编辑 ]

论坛徽章:
0
5 [报告]
发表于 2007-10-26 19:03 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
6 [报告]
发表于 2007-10-26 19:46 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
7 [报告]
发表于 2007-10-26 21:15 |只看该作者
原帖由 jamesr 于 2007-10-26 19:46 发表
非蛮力:

#include
static char array[10]={0};

void put(int a)
{
        int s=0;
        for(int i=0;i



可惜是错误的算法
你试一下
fun(199100)
fun(19100)

你的算法结果是错的

论坛徽章:
0
8 [报告]
发表于 2007-10-26 22:28 |只看该作者
假设题目描述的b对正整数a的关系可以表示为函数b=foo(a);
引理1:foo(X[j]*10^j)
= 1*10^(j+1) + (X[j]-1)
其中X[j]!=0,j=0,1,2,... (待证明)
例如:
foo(1)   = 10;
foo(20)  = 101;
foo(300) = 1002;
引理2:foo(X[N]*10^N + ... + X[j+1]*10^(j+1) + X[j]*10^j)
= X[N]*10^N + ... + X[j+1]*10^(j+1) + 1*10^(j+1) +(X[j]-1)
其中X[N]!=0,X[j+1]!=9,X[j]!=0,j=0,1,2,... (待证明)
例如:
foo(951)   = 960;
foo(8620)  = 8701;
foo(57300) = 58002;
引理3:foo(X[N]*10^N + ... + X[i+1]*10^(i+1) + X*10^i + ... + X[j+1]*10^(j+1) + X[j]*10^j)
= X[N]*10^N + ... + X[i+1]*10^(i+1) +1*10^(i+1) + (X[j]-1)*10^(i-j) + X*10^(i-j-1) + ... + X[j+1]*10^0
其中X[N]!=0,X[j]!=0,X[j+1]直到X == 9, i,j=0,1,2,... (待证明)
例如:
foo(1591)     = 1609;
foo(169920)   = 170199;
foo(17999300) = 18002999;
一个正整数a肯定可以表示成
a = X[N]*10^N + ... + X[i+1]*10^(i+1) + X*10^i + ... + X[j+1]*10^(j+1) + X[j]*10^j
的形式
根据引理3就可以解
如果程序来实现,只要分解出a的每一十进制位的值即可。
关于引理证明问题,我觉得引理看起来很自然,一时想不到简单明了方法证明之。
请诸位高手指点

如果a是负数,研究中……


-----
#include <stdio.h>
unsigned int power(unsigned int base, unsigned int n)
{
unsigned int val;

val = 1;
while(n--)
{
  val *= base;
}
return val;
}
unsigned int fill_digit(unsigned int digit,
  unsigned int *digitArray)
{
int i;
i = 0;
do
{
  digitArray = digit%10;
  digit /= 10;
  i++;
}while(digit);
return i;
}
unsigned int foo(unsigned int a)
{
unsigned int digitArray[20];
unsigned int digitWidth;
unsigned int b;
unsigned int i;
unsigned int j;
unsigned int idx;
digitWidth = fill_digit(a, digitArray);
for(idx=0; idx<digitWidth; idx++)
{
  if(0 != digitArray[idx])
  {
   j = idx;
   i = idx;
   break;
  }
}

idx++;
if(idx<digitWidth)
{
  if(9 == digitArray[idx])
  {
   for(; idx<digitWidth; idx++)
   {
    if(9 == digitArray[idx])
    {
     i = idx;
    }
    else
    {
     break;
    }
   }
  }
}
b = 0;
for(idx=digitWidth-1; idx>=0; idx--)
{
  if(idx>i)
  {
   b += digitArray[idx]*power(10, idx);
   continue;
  }
  if(idx>j)
  {
   b += 9*power(10, idx-j-1);
   continue;
  }
  break;
}
b += power(10, i+1) + (digitArray[j]-1)*power(10, i-j);
return b;
}
int main(int argc, char *argv[])
{
unsigned int a;
if(argc > 1)
{
  a = atoi(argv[1]);
  if(a)
  {
   printf("%d -- %d\n", a, foo(a));
  }
}
return 0;
}

-----

[ 本帖最后由 sanbiangongzi 于 2007-10-27 08:23 编辑 ]

论坛徽章:
0
9 [报告]
发表于 2007-10-26 23:11 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
10 [报告]
发表于 2007-10-26 23:59 |只看该作者
把a表示为x[k]...x[1]a9...9b0...0,其中a != 9, b != 0(前面的x[i]可能没有)
step1:将原串变为x[k]...[1]ab0...09...9
step2:再次变换为x[k]...x[1](a+1)0...0(b-1)9...9,over

另外,对于一个相关问题,找与a的临近数b,b满足:b < a,且b为满足b < a的最大数,a和b各位数之和相同
相似的解决方案:把a表示为x[k]...x[1]a0...0b9...9,其中a != 0, b != 9
step1:x[k]...x[1]a9...90...0b
step2:x[k]...x[1](a-1)9...9(b+1)0...0

源程序就不写了

[[i] 本帖最后由 tyc611 于 2007-10-27 00:04 编辑 [/i]]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP