彩票問題(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來檢驗,通過。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章