一个数组求交集的问题, 大家帮忙看看(内详)

woshinanren 2009-05-08 10:20:35
假设有n个数组a[m],(可以看作a[n][m])
a[m]表示一个分成m段的物体的每段的状态, a[m]的元素值为0或1,0表示这段不可用,1表示可用
则a[m]表示的物体可用的部分等于所有1的和, 为s(a[m])=A
求一个公共解b[m], 假定其和为s(b[m])=B
如果a[m]包含b[m],也就是b[m]是a[m]的子集, 则a[m]中的b[m]部分可以使用, 其和等于b[m]的和,B。
反之如果a[m]不能完全包含b[m],则a[m]都不可用,其和为0

现在要求b[m]使n个a[m]的总和最大.
...全文
288 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
lvjaio5241 2009-05-24
  • 打赏
  • 举报
回复
学习
thesecretblue 2009-05-24
  • 打赏
  • 举报
回复
学习了!!!
iwantnon 2009-05-14
  • 打赏
  • 举报
回复
2,大些的例子:
A=...%集合簇{ai}
[1 1 1 0 0 1 1 1 1 1
1 1 1 1 1 0 1 1 1 1
1 1 1 0 1 1 1 0 1 0
1 0 1 1 1 1 0 1 1 1
0 1 0 1 1 1 0 0 1 1
1 1 1 1 1 1 1 0 1 1
1 1 1 0 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1
1 1 1 0 1 1 1 1 0 1
1 1 1 1 0 0 1 1 1 1
1 0 1 1 1 1 1 1 0 1
1 0 1 1 1 1 0 1 1 1
1 0 1 0 1 1 1 1 0 1
1 1 1 1 1 1 1 0 1 1
0 1 0 0 1 1 1 1 0 0
1 1 1 1 1 1 1 1 1 1
1 1 0 0 1 1 1 1 1 0
0 0 1 1 1 1 1 1 1 0
1 0 1 1 0 1 1 1 0 1
0 0 1 0 1 0 1 0 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 0 1
0 1 1 1 1 1 1 1 1 1
0 1 0 1 1 1 1 1 0 1
1 1 0 1 0 1 1 0 0 1
0 1 0 1 1 1 0 1 1 1
1 0 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 0 1
0 1 0 1 1 1 0 1 1 1
1 1 1 1 1 1 1 1 1 0
0 0 0 1 1 0 1 1 1 1
1 1 1 1 0 0 1 1 1 0
1 0 1 1 1 1 0 1 1 1
1 1 1 1 1 0 0 1 1 1
1 1 0 1 0 1 1 1 0 1
1 1 0 1 1 0 1 1 1 1
1 1 1 1 1 1 1 0 1 0
1 1 1 1 1 1 1 1 1 1
0 1 1 1 1 0 1 1 0 0
0 0 0 1 0 0 1 1 1 0
1 0 1 0 0 0 0 0 0 1
0 1 0 1 0 1 1 0 1 1
1 1 1 1 1 1 1 1 1 1
0 0 1 0 1 1 1 1 1 1
0 1 1 1 1 1 1 0 1 0
1 1 0 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 0 1
0 1 1 0 1 1 1 1 1 1
1 0 1 1 0 1 0 1 1 1
1 1 0 1 1 0 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 0 1 1 0
1 1 0 1 0 1 1 1 0 1
1 1 1 0 1 0 1 1 1 1
0 0 0 1 1 1 1 1 1 1
1 1 1 1 1 1 0 1 1 1
1 1 1 1 0 1 1 1 0 0
1 0 1 1 1 0 1 1 1 1
1 0 1 0 0 0 1 1 0 1
1 1 0 1 1 1 1 1 0 1
1 1 1 1 1 1 0 0 0 1
1 0 1 1 1 1 1 0 1 1
0 0 1 1 1 1 1 1 1 1
1 1 1 0 1 1 0 1 1 1
1 1 1 0 1 1 1 0 0 0
1 1 1 1 1 1 0 1 1 0
0 1 1 1 0 1 1 0 0 1
1 1 1 1 0 1 1 1 1 1
1 1 1 1 1 0 1 1 0 0
0 1 1 1 1 1 1 1 0 1
1 1 0 0 1 0 1 1 1 1
1 0 1 1 1 0 1 1 1 1
1 1 1 1 1 1 1 1 1 1
0 1 1 1 0 1 1 1 0 1
1 1 1 1 1 0 1 1 1 1
0 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 0
1 0 1 0 1 0 1 1 1 0
1 0 1 1 1 1 0 1 1 1
1 1 1 0 0 1 0 1 0 1
1 1 0 1 1 1 1 1 1 1
1 1 1 0 0 1 1 1 1 0
1 1 1 1 1 1 1 1 0 1
1 1 1 1 1 1 1 1 1 1
1 0 0 1 0 1 0 1 1 1
1 1 1 1 0 1 1 0 1 0
1 1 0 1 1 1 1 1 0 1
1 1 1 1 0 1 1 1 0 1
1 0 0 1 0 0 0 1 1 1
1 0 1 1 1 1 1 0 1 1
0 1 1 1 1 0 0 1 1 1
0 1 0 1 1 1 1 1 1 0
1 1 1 1 1 1 1 1 0 1
1 1 1 1 1 1 0 1 1 1
1 1 1 1 0 0 1 1 1 1
1 0 1 0 0 1 1 1 1 1
1 1 1 1 1 1 1 0 1 1
1 1 1 1 1 0 1 1 0 1
1 0 1 0 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 0];
solve(A);
运行结果:
>>eg2
结果:
目标值:
172
b:
0 0 0 1 1 0 0 1 0 1
iwantnon 2009-05-14
  • 打赏
  • 举报
回复
用贪心方法写了一个,看看优化效果是否可接受:
matlab代码:
function solve(A)
[leni,lenj]=size(A);
b=zeros(1,lenj);%集合b
m=leni;%A中包含b的行数
n=0;%集合b的大小
while 1
%尝试当前b中哪个0元素改成1较好
trs=ones(1,lenj)*inf;%保存各种尝试下的m的减少量
for i=1:lenj
if b(i)==0
%假想将b(i)改成1
%计算A中第i列为0的行(即不包含修改后的b的行)的个数,也就是m减少的量
dm=size(find(A(:,i)==0),1);
trs(i)=dm;
end
end
%求trs中最小值
[dm,i]=min(trs);%即当前将b(i)改成1可使m减小量最小,为dm
%进行实际操作
if (m-dm)*(n+1)>=m*n%如果按此改法确实能改进目标值,则进行实际修改
%(经分析此处用">="比用">"更好--为跨过局部最优解提供机会)
b(i)=1;
n=n+1;
m=m-dm;
A=A(A(:,i)==1,:);%A中不包含当前b的行被删除
else%否则已达到局部最优,结束
break;
end
end
disp('结果:');
disp('目标值:');
disp(m*n);
disp('b:');
disp(b);
end
下面是两个例子:
1,较小的例子:
A=...%集合族{ai}
[1 0 1 0 0 1 1 1 1
1 1 1 0 1 1 0 1 1
0 1 1 0 1 0 1 1 1
1 1 1 0 1 0 1 1 1
1 1 1 1 1 1 1 1 1
1 1 0 1 1 0 1 1 1];
运行结果:
>>eg1
结果:
目标值:
20
b:
1 1 0 0 1 0 0 1 1
solve(A);
2,大些的例子:
(见楼下)
iwantnon2 2009-05-14
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 iwantnon 的回复:]
下面是两个例子:
1,较小的例子:
A=...%集合族{ai}
[1 0 1 0 0 1 1 1 1
1 1 1 0 1 1 0 1 1
0 1 1 0 1 0 1 1 1
1 1 1 0 1 0 1 1 1
1 1 1 1 1 1 1 1 1
1 1 0 1 1 0 1 1 1];
运行结果:
>>eg1
结果:
目标值:
20
b:
1 1 0 0 1 0 0 1 1
[/Quote]
刚才编了一个穷举程序验证了一下,结果也是20,所以贪心算法对此例得到了最优解!
iwantnon 2009-05-14
  • 打赏
  • 举报
回复
18楼举子举失误了,我还以为100*10的矩阵比6*9的矩阵规模大的,想了一下,对于楼主的问题,两个例子其实是同一个。
应该举一个10*100的才对,或者说18楼的A忘记转置了,应该是这样:
A=...%集合簇{ai}
[1 1 1 0 0 1 1 1 1 1
1 1 1 1 1 0 1 1 1 1
1 1 1 0 1 1 1 0 1 0
1 0 1 1 1 1 0 1 1 1
0 1 0 1 1 1 0 0 1 1
1 1 1 1 1 1 1 0 1 1
1 1 1 0 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1
1 1 1 0 1 1 1 1 0 1
1 1 1 1 0 0 1 1 1 1
1 0 1 1 1 1 1 1 0 1
1 0 1 1 1 1 0 1 1 1
1 0 1 0 1 1 1 1 0 1
1 1 1 1 1 1 1 0 1 1
0 1 0 0 1 1 1 1 0 0
1 1 1 1 1 1 1 1 1 1
1 1 0 0 1 1 1 1 1 0
0 0 1 1 1 1 1 1 1 0
1 0 1 1 0 1 1 1 0 1
0 0 1 0 1 0 1 0 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 0 1
0 1 1 1 1 1 1 1 1 1
0 1 0 1 1 1 1 1 0 1
1 1 0 1 0 1 1 0 0 1
0 1 0 1 1 1 0 1 1 1
1 0 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 0 1
0 1 0 1 1 1 0 1 1 1
1 1 1 1 1 1 1 1 1 0
0 0 0 1 1 0 1 1 1 1
1 1 1 1 0 0 1 1 1 0
1 0 1 1 1 1 0 1 1 1
1 1 1 1 1 0 0 1 1 1
1 1 0 1 0 1 1 1 0 1
1 1 0 1 1 0 1 1 1 1
1 1 1 1 1 1 1 0 1 0
1 1 1 1 1 1 1 1 1 1
0 1 1 1 1 0 1 1 0 0
0 0 0 1 0 0 1 1 1 0
1 0 1 0 0 0 0 0 0 1
0 1 0 1 0 1 1 0 1 1
1 1 1 1 1 1 1 1 1 1
0 0 1 0 1 1 1 1 1 1
0 1 1 1 1 1 1 0 1 0
1 1 0 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 0 1
0 1 1 0 1 1 1 1 1 1
1 0 1 1 0 1 0 1 1 1
1 1 0 1 1 0 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 0 1 1 0
1 1 0 1 0 1 1 1 0 1
1 1 1 0 1 0 1 1 1 1
0 0 0 1 1 1 1 1 1 1
1 1 1 1 1 1 0 1 1 1
1 1 1 1 0 1 1 1 0 0
1 0 1 1 1 0 1 1 1 1
1 0 1 0 0 0 1 1 0 1
1 1 0 1 1 1 1 1 0 1
1 1 1 1 1 1 0 0 0 1
1 0 1 1 1 1 1 0 1 1
0 0 1 1 1 1 1 1 1 1
1 1 1 0 1 1 0 1 1 1
1 1 1 0 1 1 1 0 0 0
1 1 1 1 1 1 0 1 1 0
0 1 1 1 0 1 1 0 0 1
1 1 1 1 0 1 1 1 1 1
1 1 1 1 1 0 1 1 0 0
0 1 1 1 1 1 1 1 0 1
1 1 0 0 1 0 1 1 1 1
1 0 1 1 1 0 1 1 1 1
1 1 1 1 1 1 1 1 1 1
0 1 1 1 0 1 1 1 0 1
1 1 1 1 1 0 1 1 1 1
0 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 0
1 0 1 0 1 0 1 1 1 0
1 0 1 1 1 1 0 1 1 1
1 1 1 0 0 1 0 1 0 1
1 1 0 1 1 1 1 1 1 1
1 1 1 0 0 1 1 1 1 0
1 1 1 1 1 1 1 1 0 1
1 1 1 1 1 1 1 1 1 1
1 0 0 1 0 1 0 1 1 1
1 1 1 1 0 1 1 0 1 0
1 1 0 1 1 1 1 1 0 1
1 1 1 1 0 1 1 1 0 1
1 0 0 1 0 0 0 1 1 1
1 0 1 1 1 1 1 0 1 1
0 1 1 1 1 0 0 1 1 1
0 1 0 1 1 1 1 1 1 0
1 1 1 1 1 1 1 1 0 1
1 1 1 1 1 1 0 1 1 1
1 1 1 1 0 0 1 1 1 1
1 0 1 0 0 1 1 1 1 1
1 1 1 1 1 1 1 0 1 1
1 1 1 1 1 0 1 1 0 1
1 0 1 0 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 0];
solve(A');
运行结果:
>>eg2
结果:
目标值:
81

b:
Columns 1 through 11

0 1 0 0 0 0 0 0 0 0 0

Columns 12 through 22

0 0 0 0 1 0 0 0 0 1 0

Columns 23 through 33

0 0 0 0 0 0 0 0 0 0 0

Columns 34 through 44

0 0 0 0 1 0 0 0 0 1 0

Columns 45 through 55

0 0 0 0 0 0 1 0 0 0 0

Columns 56 through 66

0 0 0 0 0 0 0 0 0 0 0

Columns 67 through 77

0 0 0 0 0 0 1 0 1 0 0

Columns 78 through 88

0 0 0 0 0 0 1 0 0 0 0

Columns 89 through 99

0 0 0 0 0 0 0 0 0 0 0

Column 100

0
coxfilur_2008 2009-05-13
  • 打赏
  • 举报
回复
Mark
绿色夹克衫 2009-05-12
  • 打赏
  • 举报
回复
LZ给个文本作测试数据吧,我帮你写一个简单的!

[Quote=引用 14 楼 woshinanren 的回复:]
数据规模不是很大 n < 50, m <= 256

上面讲的听不明白, 有没有人研究过这个东西?
[/Quote]
woshinanren 2009-05-12
  • 打赏
  • 举报
回复
数据规模不是很大 n < 50, m <= 256

上面讲的听不明白, 有没有人研究过这个东西?
绿色夹克衫 2009-05-10
  • 打赏
  • 举报
回复
我说的是属于硬搜的方法(也许还有什么更好的方法),降低计算量主要是靠剪枝,DP可能还在其次,

状态方程应当是:opt(m)=max{opt(m-1),选中的行数(即所有满足:a[m]包含b[m]的a[m]个数)*选中的列数(opt(m-1)选中的列数 + 1)};

这类问题在数据量大的时候,运算量本身就是指数级的,只有在N和M不是很大的时候能够求解

[Quote=引用 11 楼 odiwlykwia 的回复:]
如果记录下上一次的所有列的选择情况,就有2^N种情况,显然是不现实的
[/Quote]
无天 2009-05-10
  • 打赏
  • 举报
回复
友情帮顶!
odiwlykwia 2009-05-09
  • 打赏
  • 举报
回复
如果记录下上一次的所有列的选择情况,就有2^N种情况,显然是不现实的
odiwlykwia 2009-05-09
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 iwantnon 的回复:]
如果没理解错的话,楼主的意思是:

[/Quote]
我也是这么理解的,这样的话:
[Quote=引用 8 楼 litaoye 的回复:]
不知道我上面说清楚了没有,其实这也是一个类似01背包的问题,将A[n][m]转化为矩阵后,
每一列都存在着2种状态,选与不选,因此类似01背包,但稍微复杂一点的地方在于,选择了该列后,
需要重新计算当前的值,而不是简单的加法,需要对当前的列与已选择的列做一次&运算,
只有&之后仍旧=true的行,被视为选中的行,然后用选中的行数*选中的列数,就是当前选中的值。

利用hash+剪枝,应该可以将效率提升到可接受的范围。
[/Quote]
这样就是错误的吧!
这样的状态方程:opt(m)=max{opt(m-1),选中的行数(即所有满足:a[m]包含b[m]的a[m]个数)*选中的列数(新的b[m]:原来的b[m]+当前列)};
可是新的b[m]不仅仅是这样一种情况;
iwantnon 2009-05-09
  • 打赏
  • 举报
回复
如果没理解错的话,楼主的意思是:
绿色夹克衫 2009-05-09
  • 打赏
  • 举报
回复
不知道我上面说清楚了没有,其实这也是一个类似01背包的问题,将A[n][m]转化为矩阵后,
每一列都存在着2种状态,选与不选,因此类似01背包,但稍微复杂一点的地方在于,选择了该列后,
需要重新计算当前的值,而不是简单的加法,需要对当前的列与已选择的列做一次&运算,
只有&之后仍旧=true的行,被视为选中的行,然后用选中的行数*选中的列数,就是当前选中的值。

利用hash+剪枝,应该可以将效率提升到可接受的范围。
sunzerui 2009-05-09
  • 打赏
  • 举报
回复
好难
顶了
关注!
绿色夹克衫 2009-05-08
  • 打赏
  • 举报
回复
又想了一下,似乎可以用dancing link来解,可以提高效率.
绿色夹克衫 2009-05-08
  • 打赏
  • 举报
回复
将A[n][m]转化为矩阵,以A[10][10]为例,假设转化后的矩阵为

1 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0
1 1 1 1 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0
1 1 1 1 1 1 0 0 0 0
1 1 1 1 1 1 1 0 0 0
1 1 1 1 1 1 1 1 0 0
1 1 1 1 1 1 1 1 1 0
1 1 1 1 1 1 1 1 1 1

问题就转化为了求最大的1的面积

当然转化为一般数据的话,没有这么明显,但可以通过动态规划来解,决定选取的列.

woshinanren 2009-05-08
  • 打赏
  • 举报
回复
会的同学贴点分析, 不一定要大段的代码
Paradin 2009-05-08
  • 打赏
  • 举报
回复
up.mark.
加载更多回复(2)

33,009

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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