打印
[C语言]

秀你智商的一个C问题,进来看看。

[复制链接]
3328|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。

使用特权

评论回复
5
lifebird| | 2015-5-31 09:51 | 只看该作者
各位坛友扁楼主,叫他藐视各位的智商。

使用特权

评论回复
6
yangwenguan| | 2015-5-31 10:30 | 只看该作者
楼主的问题描述能力有待加强:
先给出一个数据集合, 再给出一个目标数, 求数据集合中任意数相加的结果,小于目标数, 结果越精确越好.

不知我漏掉什么没有?

使用特权

评论回复
7
lxyppc| | 2015-5-31 11:44 | 只看该作者
算法导论,kp问题
目测复杂度是o(n^2)
如果预处理了,时间复杂度可以到o(log(n)),空间复杂度到o(n!)
预处理方式如下:将序列扩展成原数与原数所有可能的和

使用特权

评论回复
8
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]是怎么算来的

使用特权

评论回复
9
chenyu988|  楼主 | 2015-5-31 13:37 | 只看该作者
lifebird 发表于 2015-5-31 09:47
用查表法,表长2的8次方,为256。

确定只有256,?用排列组合一算,怎么远远不止256啊

使用特权

评论回复
10
chenyu988|  楼主 | 2015-5-31 13:39 | 只看该作者
yangwenguan 发表于 2015-5-31 10:30
楼主的问题描述能力有待加强:
先给出一个数据集合, 再给出一个目标数, 求数据集合中任意数相加的结果,小于 ...

漏了一点,优先使用最大的数

使用特权

评论回复
11
chenyu988|  楼主 | 2015-5-31 13:40 | 只看该作者
lxyppc 发表于 2015-5-31 11:44
算法导论,kp问题
目测复杂度是o(n^2)
如果预处理了,时间复杂度可以到o(log(n)),空间复杂度到o(n ...

有点深奥 不懂

使用特权

评论回复
12
yangwenguan| | 2015-5-31 16:07 | 只看该作者
先给出一个数据集合, 再给出一个目标数, 求数据集合中任意数相加的结果,小于目标数, 而结果越逼近目标数越好.

使用特权

评论回复
13
wangpeng59| | 2015-5-31 16:13 | 只看该作者
这个发某个c语言的论坛会比较好吧?单片机关于这种的运算比较少

使用特权

评论回复
14
chenyu988|  楼主 | 2015-5-31 17:18 | 只看该作者
NE5532 发表于 2015-5-30 23:58
抢占沙发,围观答案。目前只想到穷举比较,所以就不发出来了。

看来我也只能比较了。。

使用特权

评论回复
15
LockYourID!| | 2015-5-31 17:19 | 只看该作者
到底是最接近优先还是取大数优先,貌似最接近就只有一种可能啊

使用特权

评论回复
16
LockYourID!| | 2015-5-31 17:37 | 只看该作者
#include <reg52.h>
/*
有一组数据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.
*/
unsigned int code elem[]={720,300,86,64,44,24,7,4};
unsigned int result[8];
void split1(unsigned int x)
{
        unsigned char i=0,j=0;
        for(i=0;i<8;i++){result[i]=0;}
        for(i=0;i<8;i++)
        {
                if(x>elem[i]){result[j]=elem[i];j++;x=x-elem[i];}
        }
}
unsigned int sum(unsigned int * arry)
{
        unsigned char i=0;
        unsigned int sumval=0;
        for(i=0;i<8;i++)
        {
                sumval=sumval+arry[i];
        }
        return(sumval);
}
void split2(unsigned int x)
{
        unsigned char i=0,j=0,Closest;
        unsigned int err,min_err=65535;
        for(i=1;i<8;i++){result[i]=0;}
        for(i=1;i!=0;i++)
        {
                if(i&0x80){result[0]=720;}else{result[0]=0;}
                if(i&0x40){result[1]=300;}else{result[1]=0;}
                if(i&0x20){result[2]=86;}else{result[2]=0;}
                if(i&0x10){result[3]=64;}else{result[3]=0;}
                if(i&0x08){result[4]=44;}else{result[4]=0;}
                if(i&0x04){result[5]=24;}else{result[5]=0;}
                if(i&0x02){result[6]=7;}else{result[6]=0;}
                if(i&0x01){result[7]=4;}else{result[7]=0;}
                if(sum(result)>=x)
      {
                        continue;
                        }
                        else
                        {
                                err=x-sum(result);
                                if(err<min_err){min_err=err;Closest=i;}
                        }
        }
                if(Closest&0x80){result[0]=720;}else{result[0]=0;}
                if(Closest&0x40){result[1]=300;}else{result[1]=0;}
                if(Closest&0x20){result[2]=86;}else{result[2]=0;}
                if(Closest&0x10){result[3]=64;}else{result[3]=0;}
                if(Closest&0x08){result[4]=44;}else{result[4]=0;}
                if(Closest&0x04){result[5]=24;}else{result[5]=0;}
                if(Closest&0x02){result[6]=7;}else{result[6]=0;}
                if(Closest&0x01){result[7]=4;}else{result[7]=0;}
}
void main()
{
        while(1)
        {
                split1(400);
                split2(400);
        }
}

使用特权

评论回复
17
lvyunhua| | 2015-5-31 21:18 | 只看该作者
楼上很牛啊!

使用特权

评论回复
18
yklstudent| | 2015-5-31 21:30 | 只看该作者
楼上也很牛啊,VIP会员,好高级的样子:lol

使用特权

评论回复
19
xbwpc| | 2015-5-31 22:08 | 只看该作者
chenyu988 发表于 2015-5-31 13:36
智商有限,看到不太明白
你都假设f为前i个数最接近j的和了,关键就是这个f是怎么算来的 ...

f[i,j]是DP决策得到的,初始边界条件可以简单确定,然后利用状态转移方程递推得到目标状态。

使用特权

评论回复
20
xbwpc| | 2015-5-31 22:11 | 只看该作者
这个问题和背包问题其实差不多,只需要稍微改动DP方程,楼主自己百度吧。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

47

主题

1107

帖子

14

粉丝