[C语言] 秀你智商的一个C问题,进来看看。

[复制链接]
3777|29
 楼主| chenyu988 发表于 2015-5-30 22:55 | 显示全部楼层 |阅读模式
本帖最后由 chenyu988 于 2015-5-30 22:58 编辑

有一组数据4,7,24,44,64,86,300,720。

输入一个值比如400,要求从上面8个值中选择若干个相加和最接近400,但不能超过400,并且要求在满足和最接近的条件下优先使用比400小,但是最接近400的值,在这里就是300了。输入400的话应该是选择300+64+24+7+4=399,因为如果选择了300+86,那剩下的只能选7和4了,300+86+7+4=397<399.

那么问题来了,任意输入一个数,C语言实现输出。

1,用if else层层判断,太繁琐。。
2,查表法,那这个表得多大。。

有没有高见。。
NE5532 发表于 2015-5-30 23:58 | 显示全部楼层
抢占沙发,围观答案。目前只想到穷举比较,所以就不发出来了。
xbwpc 发表于 2015-5-31 09:39 | 显示全部楼层
如果都是整数的话应该可以用动态规划解决,设f[i,j]为前i个数最接近j的和,状态转移时f[i,j]取f[i-k,j-num[i]]+num[i](k=1..i)和f[i,j]中的最优值。
lifebird 发表于 2015-5-31 09:47 | 显示全部楼层
用查表法,表长2的8次方,为256。
lifebird 发表于 2015-5-31 09:51 | 显示全部楼层
各位坛友扁楼主,叫他藐视各位的智商。
yangwenguan 发表于 2015-5-31 10:30 | 显示全部楼层
楼主的问题描述能力有待加强:
先给出一个数据集合, 再给出一个目标数, 求数据集合中任意数相加的结果,小于目标数, 结果越精确越好.

不知我漏掉什么没有?
lxyppc 发表于 2015-5-31 11:44 来自手机 | 显示全部楼层
算法导论,kp问题
目测复杂度是o(n^2)
如果预处理了,时间复杂度可以到o(log(n)),空间复杂度到o(n!)
预处理方式如下:将序列扩展成原数与原数所有可能的和
 楼主| chenyu988 发表于 2015-5-31 13:36 | 显示全部楼层
xbwpc 发表于 2015-5-31 09:39
如果都是整数的话应该可以用动态规划解决,设f为前i个数最接近j的和,状态转移时f取f]+num(k=1..i)和f中的 ...

智商有限,看到不太明白
你都假设f[i,j]为前i个数最接近j的和了,关键就是这个f[i,j]是怎么算来的
 楼主| chenyu988 发表于 2015-5-31 13:37 | 显示全部楼层
lifebird 发表于 2015-5-31 09:47
用查表法,表长2的8次方,为256。

确定只有256,?用排列组合一算,怎么远远不止256啊
 楼主| chenyu988 发表于 2015-5-31 13:39 | 显示全部楼层
yangwenguan 发表于 2015-5-31 10:30
楼主的问题描述能力有待加强:
先给出一个数据集合, 再给出一个目标数, 求数据集合中任意数相加的结果,小于 ...

漏了一点,优先使用最大的数
 楼主| chenyu988 发表于 2015-5-31 13:40 | 显示全部楼层
lxyppc 发表于 2015-5-31 11:44
算法导论,kp问题
目测复杂度是o(n^2)
如果预处理了,时间复杂度可以到o(log(n)),空间复杂度到o(n ...

有点深奥 不懂
yangwenguan 发表于 2015-5-31 16:07 | 显示全部楼层
先给出一个数据集合, 再给出一个目标数, 求数据集合中任意数相加的结果,小于目标数, 而结果越逼近目标数越好.
wangpeng59 发表于 2015-5-31 16:13 | 显示全部楼层
这个发某个c语言的论坛会比较好吧?单片机关于这种的运算比较少
 楼主| chenyu988 发表于 2015-5-31 17:18 | 显示全部楼层
NE5532 发表于 2015-5-30 23:58
抢占沙发,围观答案。目前只想到穷举比较,所以就不发出来了。

看来我也只能比较了。。
LockYourID! 发表于 2015-5-31 17:19 | 显示全部楼层
到底是最接近优先还是取大数优先,貌似最接近就只有一种可能啊
LockYourID! 发表于 2015-5-31 17:37 | 显示全部楼层
  1. #include <reg52.h>
  2. /*
  3. 有一组数据4,7,24,44,64,86,300,720。输入一个值比如400,
  4. 要求从上面8个值中选择若干个相加和最接近400,但不能超过400
  5. 并且要求在满足和最接近的条件下优先使用比400小,但是最接近400的值,
  6. 在这里就是300了。输入400的话应该是选择300+64+24+7+4=399,
  7. 因为如果选择了300+86,那剩下的只能选7和4了,300+86+7+4=397<399.
  8. */
  9. unsigned int code elem[]={720,300,86,64,44,24,7,4};
  10. unsigned int result[8];
  11. void split1(unsigned int x)
  12. {
  13.         unsigned char i=0,j=0;
  14.         for(i=0;i<8;i++){result[i]=0;}
  15.         for(i=0;i<8;i++)
  16.         {
  17.                 if(x>elem[i]){result[j]=elem[i];j++;x=x-elem[i];}
  18.         }
  19. }
  20. unsigned int sum(unsigned int * arry)
  21. {
  22.         unsigned char i=0;
  23.         unsigned int sumval=0;
  24.         for(i=0;i<8;i++)
  25.         {
  26.                 sumval=sumval+arry[i];
  27.         }
  28.         return(sumval);
  29. }
  30. void split2(unsigned int x)
  31. {
  32.         unsigned char i=0,j=0,Closest;
  33.         unsigned int err,min_err=65535;
  34.         for(i=1;i<8;i++){result[i]=0;}
  35.         for(i=1;i!=0;i++)
  36.         {
  37.                 if(i&0x80){result[0]=720;}else{result[0]=0;}
  38.                 if(i&0x40){result[1]=300;}else{result[1]=0;}
  39.                 if(i&0x20){result[2]=86;}else{result[2]=0;}
  40.                 if(i&0x10){result[3]=64;}else{result[3]=0;}
  41.                 if(i&0x08){result[4]=44;}else{result[4]=0;}
  42.                 if(i&0x04){result[5]=24;}else{result[5]=0;}
  43.                 if(i&0x02){result[6]=7;}else{result[6]=0;}
  44.                 if(i&0x01){result[7]=4;}else{result[7]=0;}
  45.                 if(sum(result)>=x)
  46.       {
  47.                         continue;
  48.                         }
  49.                         else
  50.                         {
  51.                                 err=x-sum(result);
  52.                                 if(err<min_err){min_err=err;Closest=i;}
  53.                         }
  54.         }
  55.                 if(Closest&0x80){result[0]=720;}else{result[0]=0;}
  56.                 if(Closest&0x40){result[1]=300;}else{result[1]=0;}
  57.                 if(Closest&0x20){result[2]=86;}else{result[2]=0;}
  58.                 if(Closest&0x10){result[3]=64;}else{result[3]=0;}
  59.                 if(Closest&0x08){result[4]=44;}else{result[4]=0;}
  60.                 if(Closest&0x04){result[5]=24;}else{result[5]=0;}
  61.                 if(Closest&0x02){result[6]=7;}else{result[6]=0;}
  62.                 if(Closest&0x01){result[7]=4;}else{result[7]=0;}
  63. }
  64. void main()
  65. {
  66.         while(1)
  67.         {
  68.                 split1(400);
  69.                 split2(400);
  70.         }
  71. }
lvyunhua 发表于 2015-5-31 21:18 | 显示全部楼层
楼上很牛啊!
yklstudent 发表于 2015-5-31 21:30 | 显示全部楼层
楼上也很牛啊,VIP会员,好高级的样子:lol
xbwpc 发表于 2015-5-31 22:08 | 显示全部楼层
chenyu988 发表于 2015-5-31 13:36
智商有限,看到不太明白
你都假设f为前i个数最接近j的和了,关键就是这个f是怎么算来的 ...

f[i,j]是DP决策得到的,初始边界条件可以简单确定,然后利用状态转移方程递推得到目标状态。
xbwpc 发表于 2015-5-31 22:11 | 显示全部楼层
这个问题和背包问题其实差不多,只需要稍微改动DP方程,楼主自己百度吧。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

47

主题

1107

帖子

14

粉丝
快速回复 在线客服 返回列表 返回顶部