高分再次求教背包问题

leitnt 2009-11-24 09:30:10
有这样一个表

编号 单价
-------------
001 1.2
002 34.5
003 11.3
004 25
005 56.8
…… ……
…… ……
-------------



如果想取其中12条记录,且合计为329(通过数量*单价实现),

编号 数量 单价 金额
------------------------------
022 2 18.00 36.00
140 4 2.00 8.00
011 1 8.70 8.70
002 2 35.00 70.00
142 1 20.90 20.90
146 5 5.30 26.50
099 3 17.70 53.10
121 2 0.70 1.40
038 2 5.20 10.40
299 5 6.20 31.00
183 2 9.00 18.00
299 5 9.00 45.00
-------------------------------

能否通过调整数量使得金额合计等于特定值?注意:取12条记录,且合计是329.最好是sql2000代码
...全文
367 45 打赏 收藏 转发到动态 举报
写回复
用AI写文章
45 条回复
切换为时间正序
请发表友善的回复…
发表回复
z812183667 2009-11-28
  • 打赏
  • 举报
回复
学习!!!
icelovey 2009-11-28
  • 打赏
  • 举报
回复
牛~`
yan11cn 2009-11-28
  • 打赏
  • 举报
回复
学习学习
beddevil 2009-11-28
  • 打赏
  • 举报
回复
学习
nianran520 2009-11-27
  • 打赏
  • 举报
回复

--最终版
/*
dbo.proc_trans_makedata '@table

'
*/
/*
--By Ken 2009-11-25
--背包问题,HRC可能用到
*/
if object_id('tb') is not null drop table tb
create table tb (code varchar(10),price dec(5,2))
insert into tb
select '001', 1.22 union all
select '002' , 34.5 union all
select '003' , 11.3 union all
select '004' , 25 union all
select '005' , 56.8 union all
select '022' ,18.00 union all
select '140' , 2.00 union all
select '011' , 8.70 union all
select '006' , 35.00 union all
select '142' , 20.90 union all
select '146' , 5.30 union all
select '099' , 17.70 union all
select '121' , 0.70 union all
select '038' , 5.20 union all
select '299' , 6.20 union all
select '183' , 9.00 union all
select '299' , 9.01

declare @count int,@row int,@i int,@id int --总行数、随机数、取出行数、匹配的行数
declare @nums dec(18,2),@rand dec(18,2) --总金额
declare @remain dec(18,2),@max_price dec(18,2) -- 剩余金额、最大单价
declare @mintotal dec(18,2)
declare @times int
declare @multiple int
--初始值
select @i = 1,@times = 0,
@nums = 2200.52,
@count = count(1) from tb
--生成id,随机取值用
select identity(int,1,1) as id,* into #temp from tb order by price
select @mintotal = sum(price) from #temp where id <= 12
if @nums < @mintotal
begin
--select '输入金额小于临界值'
drop table #temp
return
end
--创建临时表
create table #temp_tb (id int,code varchar(10),nums int,price dec(5,2),total as price*nums)

select @remain = @nums
while @remain <> 0
begin
--随机取12行
while @i <= 12
begin
select @row = convert(int,(rand(checksum(newid()))*@count)) + 1
if EXISTS (select 1 from #temp_tb where id = @row)
begin
select @row = min(id) from #temp
where id not in (select id from #temp_tb)
end
insert into #temp_tb(id,code,nums,price)
select id,code,1,price from #temp where id = @row
select @i = @i + 1
end
--倍数
select @rand = sum(price) from #temp_tb
select @multiple = cast(@nums/@rand as int) - 5 --可自选
if @multiple > 0
begin
update #temp_tb set nums = @multiple
end
--剩余金额
select @remain = @nums - sum(nums*price) from #temp_tb
select @max_price = avg(price) from #temp_tb
--分配nums值
while @remain > @max_price
begin
update #temp_tb set nums = nums+1
where id = convert(int,(rand(checksum(newid()))*@count)) + 1
select @remain = @nums - sum(nums*price) from #temp_tb
end
--获取匹配行
select @id = max(id) from #temp_tb where @remain/price = cast(@remain/price as int)
and @remain > 0
--有
if @id is not null
begin
update #temp_tb set nums = nums + @remain/price
where id = @id
select @remain = 0
end
--无则重新循环
else
begin
delete from #temp_tb
select @i = 1
select @remain = @nums
select @times = @times + 1
if @times = 1000 --设置循环次数,匹配不了就退出循环
begin
break
end
end
end
select sum(total) as 总金额 from #temp_tb
select * from #temp_tb
drop table #temp,#temp_tb

ysx003 2009-11-27
  • 打赏
  • 举报
回复
呵呵 我是初学者
进来看看
帮不上忙
不好意思
Mirana_NightShade 2009-11-26
  • 打赏
  • 举报
回复
up
syw_java 2009-11-25
  • 打赏
  • 举报
回复
有难度
envykok 2009-11-25
  • 打赏
  • 举报
回复
人工智能 -- 先把所有记录拿出再用搜索 树 吧
zhouyongyang 2009-11-25
  • 打赏
  • 举报
回复
我也支持一下吧,学习
guguda2008 2009-11-25
  • 打赏
  • 举报
回复
上次不是写过吗?没人写下半段?
kldeng_05 2009-11-25
  • 打赏
  • 举报
回复
Mark,等高手~
renadg 2009-11-25
  • 打赏
  • 举报
回复
高手快来,快来!!!
icelovey 2009-11-25
  • 打赏
  • 举报
回复
坐等高手啦~
  • 打赏
  • 举报
回复
.
nianran520 2009-11-25
  • 打赏
  • 举报
回复

--应该没什么问题,有其他需求自己再改改
nianran520 2009-11-25
  • 打赏
  • 举报
回复

if @nums < @mintotal
begin
select '输入金额小于临界值'
drop table #temp --这里加上这句
return
end
nianran520 2009-11-25
  • 打赏
  • 举报
回复

--定义参数那加上
declare @times int
select @times = 0
--这里加
--无则重新循环
else
begin
delete from #temp_tb
select @i = 1
select @remain = @nums
select @times = @times + 1
if @times = 1000
begin
break
end
end
leitnt 2009-11-25
  • 打赏
  • 举报
回复
楼上重复操作会出现错误。如果确实无法找到匹配项(例如要取总金额100),应该从哪儿退出循环呢?
nianran520 2009-11-25
  • 打赏
  • 举报
回复

if object_id('tb') is not null drop table tb
create table tb (code varchar(10),price dec(5,2))
insert into tb
select '001', 1.22 union all
select '002' , 34.5 union all
select '003' , 11.3 union all
select '004' , 25 union all
select '005' , 56.8 union all
select '022' ,18.00 union all
select '140' , 2.00 union all
select '011' , 8.70 union all
select '006' , 35.00 union all
select '142' , 20.90 union all
select '146' , 5.30 union all
select '099' , 17.70 union all
select '121' , 0.70 union all
select '038' , 5.20 union all
select '299' , 6.20 union all
select '183' , 9.00 union all
select '299' , 9.01

declare @count int,@row int,@i int,@id int --总行数、随机数、取出行数、匹配的行数
declare @nums dec(18,2) --总金额
declare @remain dec(18,2),@max_price dec(18,2) -- 剩余金额、最大单价
declare @mintotal dec(18,2)
--初始值
select @i = 1,
@nums = 9.9,
@count = count(1) from tb
--生成id,随机取值用
select identity(int,1,1) as id,* into #temp from tb order by price
select @mintotal = sum(price) from #temp where id <= 12
if @nums < @mintotal
begin
select '输入金额小于临界值'
return
end
--创建临时表
create table #temp_tb (id int,code varchar(10),nums int,price dec(5,2),total as price*nums)

select @remain = @nums
while @remain <> 0
begin
--随机取12行
while @i <= 12
begin
select @row = convert(int,(rand(checksum(newid()))*@count)) + 1
if EXISTS (select 1 from #temp_tb where id = @row)
begin
select @row = min(id) from #temp
where id not in (select id from #temp_tb)
end
insert into #temp_tb(id,code,nums,price)
select id,code,1,price from #temp where id = @row
select @i = @i + 1
end
--剩余金额
select @remain = @nums - sum(nums*price) from #temp_tb
select @max_price = avg(price) from #temp_tb
--分配nums值
while @remain > @max_price
begin
update #temp_tb set nums = nums+1
where id = convert(int,(rand(checksum(newid()))*@count)) + 1
select @remain = @nums - sum(nums*price) from #temp_tb
end
--获取匹配行
select @id = max(id) from #temp_tb where @remain/price = cast(@remain/price as int)
and @remain > 0
--有
if @id is not null
begin
update #temp_tb set nums = nums + @remain/price
where id = @id
select @remain = 0
end
--无则重新循环
else
begin
delete from #temp_tb
select @i = 1
select @remain = @nums
end
end
select sum(total) as 总金额 from #temp_tb
select * from #temp_tb
drop table #temp,#temp_tb

加载更多回复(24)

34,576

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧