優先隊列分支限界法解部落沖突問題

算法思路:

  • 構建解空間樹(二叉樹)
  • 以廣度優先遍歷解空間樹,對每個結點進行約束函數和限界函數判斷
  • 約束函數:若要入選隊伍,則必須與其他隊員無仇
for(int j=i-1;j>0;bnode=bnode.parent,j--){  
                if(bnode.leftChild&&a[i][j]==1){  
                    ok=false;  
                    break;  
                }  
  • 約束函數:當前團最大結點大于最有解
if(cn+n-i>=bestn){//右子樹可能含有最優解  
                addLiveNode(cn+n-i,cn,i+1,enode,false);  
            }  
  • 當遍歷到其中一個葉子結點,則算法結束。

完整代碼如下:

import java.util.Collections;  
import java.util.LinkedList;  
class BBnode{                                 //構建結點類
    BBnode parent;
    boolean leftChild;
    public BBnode(BBnode parent, boolean leftChild)
    {
        super();
        this.parent = parent;
        this.leftChild = leftChild;
    }
    
}
class HeapNode implements Comparable{   //構建隊列結點
    BBnode liveNode;
    int upperSize;                                    //當前團最大結點數(已知+未知)
    int cliqueSize;                                    //當前團頂點數
    int level;                                             //所處層數
    
    public HeapNode(BBnode liveNode, int upperSize, int cliqueSize, int level)
    {
        super();
        this.liveNode = liveNode;
        this.upperSize = upperSize;
        this.cliqueSize = cliqueSize;
        this.level = level;
    }

    @Override
    public int compareTo(Object o)
    {
        // TODO Auto-generated method stub
        int xup=((HeapNode)o).upperSize;
        if(upperSize<xup)return 1;
        if(upperSize==xup)return 0;
        return -1;
    }
    
}
class MaxHeap{
    int[] value;
    int heapsize;
    public void put(HeapNode node){
        
    }
}
public class BBClique
{
    static int[] x;
    static int n;
    static int cn;//當前隊伍人數
    static int bestn;//最大隊伍人數
    static int[] bestx;
    static int[][] a;
    static  LinkedList<HeapNode> heap; 
    public BBClique(int[][] a){  
        this.a=a;  
        heap=new LinkedList<HeapNode>();  
    }
    public void addLiveNode(int up,int size,int lev,BBnode par,boolean ch){  
        BBnode enode=new BBnode(par,ch);  
        HeapNode h=new HeapNode(enode,up,size,lev);  
        heap.add(h);  
        Collections.sort(heap);  
    } 
    public int bbMaxClique(int[] bestx){  
        int n=bestx.length-1;  
        heap= new LinkedList<HeapNode>();
        //初始化(初始數據)  
        BBnode enode=null;  
        int i=1;  
        int cn=0;  
        int bestn=0;  
          
        //搜索子集空間樹  
        while(i!=n+1){//非葉節點  
            boolean ok=true;  
            BBnode bnode=enode;  
            for(int j=i-1;j>0;bnode=bnode.parent,j--){  
                if(bnode.leftChild&&a[i][j]==1){  
                    ok=false;  
                    break;  
                }  
               
            }  
            if(ok){//左兒子結點為可行結點  
                if(cn+1>bestn)  
                    bestn=cn+1;  
                addLiveNode(cn+n-i+1,cn+1,i+1,enode,true);  
            }  
            if(cn+n-i>=bestn){//右子樹可能含有最優解  
                addLiveNode(cn+n-i,cn,i+1,enode,false);  
            }  
              
            //取下一個擴展結點  
            HeapNode node=heap.poll();  
            enode=node.liveNode;  
            cn=node.cliqueSize;  
            i=node.level;  
        }  
          
        //構造當前最優解  
        for(int j=n;j>0;j--){  
            bestx[j]=enode.leftChild?1:0;  
            enode=enode.parent;  
              
        }  
         
        return bestn;  
    }
    public static void main(String[] args)
    {
        int[] c1={10,1,2,2,2,3,3,4,5,6,6,7,8,9};
        int[] c2={12,2,4,3,6,5,6,5,6,8,10,9,10,10};
        n=12;
        cn=0;
        bestn=0;
        bestx=new int[n+1];
        x=new int[n+1];
        a=new int[n+1][n+1];
        for(int h1=1;h1<a.length;h1++){
            a[0][h1]=h1;
            a[h1][0]=h1;
        }
        for(int h1=0;h1<c1.length;h1++){
            a[c1[h1]][c2[h1]]=1;
            a[c2[h1]][c1[h1]]=1;
        }
        BBClique bb=new BBClique(a);
        
        bestn=bb.bbMaxClique(bestx);
        System.out.println("*******優先隊列分支界限法**********");
        System.out.println("敵對關系:");
        for(int h1=0;h1<c1.length;h1++){
            System.out.print(c1[h1]+" vs "+c2[h1]);
            System.out.println();
        }
        
        System.out.println("隊伍最大人數達: "+bestn);
        System.out.print("分別是:");
        for(int h4=1;h4<bestx.length;h4++){
            if(bestx[h4]==1){
                System.out.print(h4+" ");
            }
        }
    }
}
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容