彩票问题(n保m)

来自:http://topic.csdn.net/u/20090715/13/2e8f688f-301d-4e9c-9672-e09114ee3f40.html?seed=1482341773

--

下面是"5保3"的例子:

五位号码,每位从0、1、3中取值,为保证与开奖号码至少三位对准,问至少需买几张彩票,这些彩票的号码为多少。

解:

所有的彩票号码构成集合S={abcde|a,b,c,d,e∈{0,1,3}},共3^5=243个元素。

对于"保3"的情况,称两个号码匹配,如果它们匹配的位数>=3。

于是就是要求号码集T,使S中任一号码在T中至少存在一个匹配号码。

把S中的243个号码看作243个顶点,如果两号码匹配,则两顶点间连一条边,这样就形成一个图G。则问题等价于:

(*)求图G中的一个最小顶点集T,使图中任意一个顶点都至少与T中一个顶点相连。

1,生成号码集S:

即求{0,1,3}的五次笛卡尔积。

2,求G的邻接矩阵mat:

计算S中任意两号码串的匹配数,形成矩阵mat,再让小于3的元素得0,>=3的元素得1。

[注:顺便说一句,此时问题又可叙述为:

在01矩阵mat中选取若干行,使其和的各分量均>=1,问至少要选几行。

也就是说,将各mat的各层看作带窟窿的油毡,要从中选若干摞起来挡雨,问至少需要几张。]

3,依据mat求T:

法一(贪心算法):

主要思想就是:每次找当前覆盖剩余元素最多的点v(注意,v也可以是已经被覆盖的点)加入T。

即用评价函数max(对覆盖面积的贡献)来指导选点。

另外,可以考虑作一些改造,如:每次选点(选毡子),不仅考虑其对覆盖面积的贡献,还考虑其对保持各处厚度(覆盖层数)均匀性的贡献--即假设我们不希望看到在铺设过程中出现某处特别厚而另一些地方则别薄的情况。那么可以引入方差--如果加入某块毡子比加入其它毡子更有利于减小各处厚度(覆盖层数)的方差,则适当提高这块毡子被选择的机会。于是可用评价函数max(对覆盖面积的贡献/各点厚度的方差)来指导选点。

经测试,两种选点规则各有利弊,多数情况下结果相同,次多数情况下前者好,但也有一些情况后者好。

对于一般"n保m"问题,将以上两个贪心解法以及前面准备数据结构的过程封装了一个函数,如下:

matlab程序:

function [rs,fullinfo]=f(n,set,m)

%n保m,set是号码各位的取值集合
%fullinfo保存两种算法分别得到的结果,rs为其中较优的那个
S=Desc(set,n);%生成号码集S

save('S.mat','S');

%求邻接矩阵mat

mat=[];
for i=1:size(S,1)
    for j=1:size(S,1)
        if i<j
            mat(i,j)=pcount(S(i,:),S(j,:));
        elseif i==j
            mat(i,j)=n;
        else
            mat(i,j)=mat(j,i);
        end
    end
end
mat=(mat>=m);
mat=mat+0;%布尔型转数值型
%分别用两种方式计算
T{1}=inT2T(core_greed(mat),S);%贪婪,不引入方差
T{2}=inT2T(core_greed_balance(mat),S);%贪婪,引入方差
%两个结果存入fullinfo
fullinfo(1).type='greed';
fullinfo(1).siz=length(T{1});
fullinfo(1).T=T{1};
fullinfo(2).type='greed_balance';
fullinfo(2).siz=length(T{2});
fullinfo(2).T=T{2};
%选中其中较好的那个
[siz,index]=min([fullinfo(1).siz,fullinfo(2).siz]);
rs.siz=siz;
rs.T=fullinfo(index).T;
end

其中

function rs=Desc(set,k)
%求set的k次笛卡尔积
if k==1
    rs=cell2mat(set');
    return;
end
rs=[];
for i=1:length(set)
    mat=Desc(set,k-1);
    mat=[set{i}.*ones(size(mat,1),1),mat];
    rs=[rs;mat];
end
end

.

function rs=pcount(str1,str2)
%计算str1和str2的匹配数
rs=0;
for i=1:length(str1)
    if str1(i)==str2(i)
        rs=rs+1;
    end
end
end

.

function inT=core_greed(mat)
%贪心
inT=zeros(1,length(mat));%各点加入T的情况
coverN=zeros(1,length(mat));%各点的覆盖层数
while(1)
    %求各点在非覆盖区投影面积
    coverS=zeros(1,length(mat));
    for i=1:length(mat)
        %求i在非覆盖区的投影面积
        for j=1:length(mat)
            if coverN(j)==0&&mat(i,j)==1
                coverS(i)=coverS(i)+1;
            end
        end%得到coverS(i)
    end%得到coverS
    [valu,index]=max(coverS);
    coverN=coverN+mat(index,:);
    inT(index)=1;
    if ~any(coverN==0)
        break;
    end
end
end

.

function inT=core_greed_balance(mat)
%贪心且引入方差
inT=zeros(1,length(mat));%各点加入T的情况
coverN=zeros(1,length(mat));%各点的覆盖层数
while(1)
    %求各点在非覆盖区投影面积
    coverS=zeros(1,length(mat));
    for i=1:length(mat)
        %求i在非覆盖区的投影面积
        for j=1:length(mat)
            if coverN(j)==0&&mat(i,j)==1
                coverS(i)=coverS(i)+1;
            end
        end%得到coverS(i)
    end%得到coverS
    %求各点加入后各点覆盖层数的方差
    coverNDev=ones(1,length(mat))*1000000;
    for i=1:length(mat)
        if inT(i)==0
            %求i加入T后的各顶点覆盖层数的方差
            tcoverN=coverN+mat(i,:);
            coverNDev(i)=Dev(tcoverN);
        end
    end%得到coverNDev
    %disp(coverNDev);
    [valu,index]=max(coverS./coverNDev);
    coverN=coverN+mat(index,:);
    inT(index)=1;
    if ~any(coverN==0)
        break;
    end
end
end

.

function rs=Dev(a)
%计算a中数据的方差
rs=sum((1/length(a)).*(a-mean(a)).^2);
end

.

function T=inT2T(inT,S)
%结合S将计算结果inT(01集合形式)转为直观的号码集T(字符单元)
T={};
for i=1:length(inT)
    if inT(i)==1
        T{end+1}=S(i,:);
    end
end
end

运行程序:

>> rs=f(5,{'0','1','3'},3)

rs =

    siz: 9
      T: {1x9 cell}

>> rs.T

ans =

    '00010'    '01113'    '03311'    '10331'    '11030'    '13133'    '30103'    '31301'    '33000'

 

检验:

检查所求得的T是否确实满足"S中任意一个号码在T中至少存在一个匹配号码"的条件,程序:

T=rs.T;

%test.m

load('S.mat');

for i=1:length(S)
    %看S{i}在T中有没有匹配
    hasmatch=false;
    for j=1:length(T)
        if pcount(S(i,:),T{j})>=3
            hasmatch=true;
            break;
        end
    end%得到hasmatch
    if hasmatch==false
        disp('测试失败!');
        disp(S{i});
        return;
    end
end
disp('测试成功!');

运行结果:

 

     测试成功!

 

另外用函数f(n,set,m)测试了另外一些例子,结果如下:

 

6保5:

    siz: 90
    '000000'    '000111'    '000333'    '001010'    '001013'    '001130'
    '001301'    '003003'    '003013'    '003031'    '003103'    '003310'
    '010003'    '010013'    '010130'    '010300'    '010303'    '011031'
    '011101'    '011300'    '013110'    '013111'    '013333'    '030130'
    '030303'    '030311'    '031031'    '031113'    '031301'    '033000'
    '033001'    '033031'    '033300'    '033333'    '100010'    '100103'
    '100313'    '100331'    '101000'    '101001'    '101333'    '103111'
    '103130'    '110001'    '110110'    '110330'    '111030'    '111103'
    '111311'    '113013'    '113131'    '113300'    '130033'    '130300'
    '131100'    '131110'    '131111'    '131113'    '131310'    '133011'
    '133130'    '133131'    '133303'    '300030'    '300031'    '300113'
    '300303'    '301100'    '301131'    '303033'    '303301'    '303310'
    '303311'    '310110'    '310133'    '310331'    '311011'    '311133'
    '311313'    '313000'    '313030'    '313100'    '313301'    '330010'
    '330101'    '330303'    '331003'    '331330'    '331331'    '333113'

6保4:
    siz: 21
    '000001'    '000331'    '001310'    '013113'    '013303'    '031000'
    '031131'    '033033'    '100033'    '103110'    '110011'    '110130'
    '111300'    '130113'    '131301'    '301113'    '303101'    '311010'
    '311030'    '330303'    '333331'

6保3:
    siz: 6
    '000000'  '000001'  '000003'  '111110'  '111111'  '333333'

5保4:
    siz: 31
    '00000'    '00111'    '00333'    '01013'    '01031'    '01130'    '01301'
    '03031'    '03103'    '03113'    '03310'    '10001'    '10110'    '10333'
    '11030'    '11103'    '11311'    '13013'    '13131'    '13300'    '30033'
    '30110'    '30303'    '30331'    '31000'    '31101'    '31313'    '31333'
    '33001'    '33011'    '33130'

5保3:
    siz: 9
    '00010'    '01113'    '03311'    '10331'    '11030'    '13133'    '30103'
    '31301'    '33000'

5保2:
    siz: 3
    '00000'    '03333'    '11111'

法二(01规划):

将mat拷贝到记事本,保存为data.txt。

(*)可以简单地描述为一个01规划问题:

为每个顶点绑定一个01变量sel,表示它是否属于T,则目标函数为:

min=∑sel

另外每个点需满足约束:

其所有邻接点sel之和>=1。

于是lingo程序如下:

model:
sets:
V/1..243/:sel;
E(V,V):link;
endsets
data:
link=@file('data.txt');!导入数据;
enddata
!变量界定;
@for(V:@bin(sel));
!目标函数;
min=@sum(V:sel);
!约束;
@for(V(i):
@sum(V(j)|link(i,j)#eq#1:sel)>=1;
);
end

运行结果:

[注:由于程序运行时间过长,只好中途中断了求解,所以得到的不是最优解,而是”Feasible solution“,不过我们看到,这个结果已经比较好了,比前面用贪心算法得到的|T|=9还要好一点儿。]

Feasible solution found.
   Objective value:                              8.000000

                       Variable           Value        Reduced Cost

                        SEL( 1)        0.000000            1.000000
                        SEL( 2)        0.000000            1.000000
                        SEL( 3)        0.000000            1.000000
                        SEL( 4)        0.000000            1.000000
                        SEL( 5)        0.000000            1.000000
                        SEL( 6)        0.000000            1.000000
                        SEL( 7)        0.000000            1.000000
                        SEL( 8)        0.000000            1.000000
                        SEL( 9)        0.000000            1.000000
                       SEL( 10)        0.000000            1.000000
                       SEL( 11)        0.000000            1.000000
                       SEL( 12)        0.000000            1.000000
                       SEL( 13)        0.000000            1.000000
                       SEL( 14)        0.000000            1.000000
                       SEL( 15)        0.000000            1.000000
                       SEL( 16)        0.000000            1.000000
                       SEL( 17)        0.000000            1.000000
                       SEL( 18)        0.000000            1.000000
                       SEL( 19)        0.000000            1.000000
                       SEL( 20)        0.000000            1.000000
                       SEL( 21)        0.000000            1.000000
                       SEL( 22)        0.000000            1.000000
                       SEL( 23)        0.000000            1.000000
                       SEL( 24)        0.000000            1.000000
                       SEL( 25)        0.000000            1.000000
                       SEL( 26)        0.000000            1.000000
                       SEL( 27)        0.000000            1.000000
                       SEL( 28)        0.000000            1.000000
                       SEL( 29)        0.000000            1.000000
                       SEL( 30)        0.000000            1.000000
                       SEL( 31)        0.000000            1.000000
                       SEL( 32)        0.000000            1.000000
                       SEL( 33)        0.000000            1.000000
                       SEL( 34)        0.000000            1.000000
                       SEL( 35)        0.000000            1.000000
                       SEL( 36)        0.000000            1.000000
                       SEL( 37)        0.000000            1.000000
                       SEL( 38)        0.000000            1.000000
                       SEL( 39)        0.000000            1.000000
                       SEL( 40)        0.000000            1.000000
                       SEL( 41)        0.000000            1.000000
                       SEL( 42)        0.000000            1.000000
                       SEL( 43)        0.000000            1.000000
                       SEL( 44)        1.000000            1.000000
                       SEL( 45)        0.000000            1.000000
                       SEL( 46)        0.000000            1.000000
                       SEL( 47)        0.000000            1.000000
                       SEL( 48)        0.000000            1.000000
                       SEL( 49)        0.000000            1.000000
                       SEL( 50)        0.000000            1.000000
                       SEL( 51)        0.000000            1.000000
                       SEL( 52)        0.000000            1.000000
                       SEL( 53)        0.000000            1.000000
                       SEL( 54)        0.000000            1.000000
                       SEL( 55)        0.000000            1.000000
                       SEL( 56)        0.000000            1.000000
                       SEL( 57)        0.000000            1.000000
                       SEL( 58)        0.000000            1.000000
                       SEL( 59)        0.000000            1.000000
                       SEL( 60)        0.000000            1.000000
                       SEL( 61)        0.000000            1.000000
                       SEL( 62)        0.000000            1.000000
                       SEL( 63)        1.000000            1.000000
                       SEL( 64)        0.000000            1.000000
                       SEL( 65)        0.000000            1.000000
                       SEL( 66)        1.000000            1.000000
                       SEL( 67)        0.000000            1.000000
                       SEL( 68)        0.000000            1.000000
                       SEL( 69)        0.000000            1.000000
                       SEL( 70)        0.000000            1.000000
                       SEL( 71)        0.000000            1.000000
                       SEL( 72)        0.000000            1.000000
                       SEL( 73)        0.000000            1.000000
                       SEL( 74)        0.000000            1.000000
                       SEL( 75)        0.000000            1.000000
                       SEL( 76)        0.000000            1.000000
                       SEL( 77)        0.000000            1.000000
                       SEL( 78)        0.000000            1.000000
                       SEL( 79)        0.000000            1.000000
                       SEL( 80)        0.000000            1.000000
                       SEL( 81)        0.000000            1.000000
                       SEL( 82)        0.000000            1.000000
                       SEL( 83)        0.000000            1.000000
                       SEL( 84)        0.000000            1.000000
                       SEL( 85)        0.000000            1.000000
                       SEL( 86)        0.000000            1.000000
                       SEL( 87)        0.000000            1.000000
                       SEL( 88)        0.000000            1.000000
                       SEL( 89)        0.000000            1.000000
                       SEL( 90)        0.000000            1.000000
                       SEL( 91)        0.000000            1.000000
                       SEL( 92)        0.000000            1.000000
                       SEL( 93)        0.000000            1.000000
                       SEL( 94)        0.000000            1.000000
                       SEL( 95)        0.000000            1.000000
                       SEL( 96)        0.000000            1.000000
                       SEL( 97)        0.000000            1.000000
                       SEL( 98)        0.000000            1.000000
                       SEL( 99)        0.000000            1.000000
                      SEL( 100)        0.000000            1.000000
                      SEL( 101)        0.000000            1.000000
                      SEL( 102)        0.000000            1.000000
                      SEL( 103)        1.000000            1.000000
                      SEL( 104)        0.000000            1.000000
                      SEL( 105)        0.000000            1.000000
                      SEL( 106)        0.000000            1.000000
                      SEL( 107)        0.000000            1.000000
                      SEL( 108)        0.000000            1.000000
                      SEL( 109)        0.000000            1.000000
                      SEL( 110)        0.000000            1.000000
                      SEL( 111)        0.000000            1.000000
                      SEL( 112)        0.000000            1.000000
                      SEL( 113)        0.000000            1.000000
                      SEL( 114)        0.000000            1.000000
                      SEL( 115)        0.000000            1.000000
                      SEL( 116)        0.000000            1.000000
                      SEL( 117)        0.000000            1.000000
                      SEL( 118)        0.000000            1.000000
                      SEL( 119)        0.000000            1.000000
                      SEL( 120)        0.000000            1.000000
                      SEL( 121)        0.000000            1.000000
                      SEL( 122)        0.000000            1.000000
                      SEL( 123)        0.000000            1.000000
                      SEL( 124)        0.000000            1.000000
                      SEL( 125)        0.000000            1.000000
                      SEL( 126)        0.000000            1.000000
                      SEL( 127)        0.000000            1.000000
                      SEL( 128)        0.000000            1.000000
                      SEL( 129)        0.000000            1.000000
                      SEL( 130)        0.000000            1.000000
                      SEL( 131)        1.000000            1.000000
                      SEL( 132)        0.000000            1.000000
                      SEL( 133)        0.000000            1.000000
                      SEL( 134)        0.000000            1.000000
                      SEL( 135)        0.000000            1.000000
                      SEL( 136)        0.000000            1.000000
                      SEL( 137)        0.000000            1.000000
                      SEL( 138)        0.000000            1.000000
                      SEL( 139)        0.000000            1.000000
                      SEL( 140)        0.000000            1.000000
                      SEL( 141)        0.000000            1.000000
                      SEL( 142)        0.000000            1.000000
                      SEL( 143)        0.000000            1.000000
                      SEL( 144)        0.000000            1.000000
                      SEL( 145)        0.000000            1.000000
                      SEL( 146)        0.000000            1.000000
                      SEL( 147)        0.000000            1.000000
                      SEL( 148)        0.000000            1.000000
                      SEL( 149)        0.000000            1.000000
                      SEL( 150)        0.000000            1.000000
                      SEL( 151)        0.000000            1.000000
                      SEL( 152)        0.000000            1.000000
                      SEL( 153)        0.000000            1.000000
                      SEL( 154)        0.000000            1.000000
                      SEL( 155)        0.000000            1.000000
                      SEL( 156)        0.000000            1.000000
                      SEL( 157)        0.000000            1.000000
                      SEL( 158)        0.000000            1.000000
                      SEL( 159)        0.000000            1.000000
                      SEL( 160)        0.000000            1.000000
                      SEL( 161)        0.000000            1.000000
                      SEL( 162)        0.000000            1.000000
                      SEL( 163)        0.000000            1.000000
                      SEL( 164)        1.000000            1.000000
                      SEL( 165)        0.000000            1.000000
                      SEL( 166)        0.000000            1.000000
                      SEL( 167)        0.000000            1.000000
                      SEL( 168)        0.000000            1.000000
                      SEL( 169)        0.000000            1.000000
                      SEL( 170)        0.000000            1.000000
                      SEL( 171)        0.000000            1.000000
                      SEL( 172)        0.000000            1.000000
                      SEL( 173)        0.000000            1.000000
                      SEL( 174)        0.000000            1.000000
                      SEL( 175)        0.000000            1.000000
                      SEL( 176)        0.000000            1.000000
                      SEL( 177)        0.000000            1.000000
                      SEL( 178)        0.000000            1.000000
                      SEL( 179)        0.000000            1.000000
                      SEL( 180)        0.000000            1.000000
                      SEL( 181)        0.000000            1.000000
                      SEL( 182)        0.000000            1.000000
                      SEL( 183)        0.000000            1.000000
                      SEL( 184)        0.000000            1.000000
                      SEL( 185)        0.000000            1.000000
                      SEL( 186)        0.000000            1.000000
                      SEL( 187)        0.000000            1.000000
                      SEL( 188)        0.000000            1.000000
                      SEL( 189)        0.000000            1.000000
                      SEL( 190)        1.000000            1.000000
                      SEL( 191)        0.000000            1.000000
                      SEL( 192)        0.000000            1.000000
                      SEL( 193)        0.000000            1.000000
                      SEL( 194)        0.000000            1.000000
                      SEL( 195)        0.000000            1.000000
                      SEL( 196)        0.000000            1.000000
                      SEL( 197)        0.000000            1.000000
                      SEL( 198)        0.000000            1.000000
                      SEL( 199)        0.000000            1.000000
                      SEL( 200)        0.000000            1.000000
                      SEL( 201)        0.000000            1.000000
                      SEL( 202)        0.000000            1.000000
                      SEL( 203)        0.000000            1.000000
                      SEL( 204)        0.000000            1.000000
                      SEL( 205)        0.000000            1.000000
                      SEL( 206)        0.000000            1.000000
                      SEL( 207)        0.000000            1.000000
                      SEL( 208)        0.000000            1.000000
                      SEL( 209)        0.000000            1.000000
                      SEL( 210)        0.000000            1.000000
                      SEL( 211)        0.000000            1.000000
                      SEL( 212)        0.000000            1.000000
                      SEL( 213)        0.000000            1.000000
                      SEL( 214)        0.000000            1.000000
                      SEL( 215)        0.000000            1.000000
                      SEL( 216)        0.000000            1.000000
                      SEL( 217)        0.000000            1.000000
                      SEL( 218)        0.000000            1.000000
                      SEL( 219)        0.000000            1.000000
                      SEL( 220)        0.000000            1.000000
                      SEL( 221)        0.000000            1.000000
                      SEL( 222)        0.000000            1.000000
                      SEL( 223)        0.000000            1.000000
                      SEL( 224)        0.000000            1.000000
                      SEL( 225)        0.000000            1.000000
                      SEL( 226)        0.000000            1.000000
                      SEL( 227)        0.000000            1.000000
                      SEL( 228)        0.000000            1.000000
                      SEL( 229)        0.000000            1.000000
                      SEL( 230)        0.000000            1.000000
                      SEL( 231)        0.000000            1.000000
                      SEL( 232)        0.000000            1.000000
                      SEL( 233)        0.000000            1.000000
                      SEL( 234)        1.000000            1.000000
                      SEL( 235)        0.000000            1.000000
                      SEL( 236)        0.000000            1.000000
                      SEL( 237)        0.000000            1.000000
                      SEL( 238)        0.000000            1.000000
                      SEL( 239)        0.000000            1.000000
                      SEL( 240)        0.000000            1.000000
                      SEL( 241)        0.000000            1.000000
                      SEL( 242)        0.000000            1.000000
                      SEL( 243)        0.000000            1.000000

 

得到近似最优解|T|=8。

下面看一下组成T的8个号码究竟是哪些:

由于数据量小,已经可以用眼睛看出来了,但是为了体现“机械化”,我们用程序来处理:)

将上面灰色部分保存为sel.txt文件,读入matlab进行处理,matlab程序如下:

sel_rd=textread('sel.txt','%s','delimiter','/n');
sel=[];
for i=1:length(sel_rd)
    sel=[sel;getvalu(sel_rd{i})];
end
index=find(sel(:,2)==1);
S=Desc({'0','1','3'},5);%号码集S
T={};
for i=1:length(index)
    T{end+1}=S(index(i),:);  
end
disp(T);

运行结果:


    '01131'    '03033'    '03103'    '10310'    '11311'    '30001'    '31000'    '33133'

 

检验:

同样用(一)中的test.m来检验,通过。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值