1. 程式人生 > 實用技巧 >7-6 部落衛隊問題 (20分)

7-6 部落衛隊問題 (20分)

原始部落byteland中的居民們為了爭搶有限的資源,經常發生衝突。幾乎每個居民都有它的仇敵。部落酋長為了組織一支保衛部落的隊伍,希望從部落的居民中選出最多的居民入伍,並保證隊伍中任何兩個人都不是仇敵。

輸入格式:

第一行兩個正整數n和m,表示byteland部落中有n個居民,居民間有m個仇敵關係, 0<n<200, 0<m<6000。居民編號為1,2,…,n。接下來輸入m行中,每行正整數u和v,表示居民u和居民v是仇敵。

輸出格式:

輸出部落衛隊最佳組建方案中包含的居民人數。之後逐個輸出衛隊組成xi, 1<=i<=n, xi=0表示居民i不在衛隊中,xi=1表示居民i在衛隊中。

輸入樣例:

7 10
1 2
1 4
2 4
2 3
2 5
2 6
3 5
3 6
4 5
5 6

  

輸出樣例:

3
1 0 1 0 0 0 1 

程式碼:

#include <bits/stdc++.h>
using namespace std;

int n; // 有 n 個居民
int m; // 有 m 個仇敵關係 
bool hate[300][7000]={0}; // a[i][j] 表示 居民 i 對 居民 j 是否 仇恨 , 1表示有 
bool inTeam[300]={0}; // 居民i是否在衛隊中 inTeam[i]=1 表示在衛隊中,初始化為0 
bool BestRecord[300
]={0}; int BestCount = 0; int GetCount( bool inTeam[] ) // 遍歷 inTeam 陣列 ,計算該方案下 衛隊的人數 { int count=0; for(int i=1;i<=n;i++) { if(inTeam[i]) count++; } return count; } void record() // 把 最好的方案記錄下來 { // 複製 inTeam 到 BestRecord for(int i=1;i<=n;i++) BestRecord[i]
= inTeam[i]; return ; } bool CanIn(int dep) // 第 dep 個村民能否進入衛隊 (和已經進入衛隊的人有沒有衝突) { for(int i=1;i<=n;i++) if( hate[dep][i] && inTeam[i] ) return 0;// dep 對 i 有仇, 而且 i 在 衛隊 return 1; } void search(int dep) // 確定 第 dep 個村民要不要進入衛隊 { // 遍歷到了葉子節點 ,得到一種方案 , 更新 BestCount 和 BestRecord ,返回 if( dep > n ) { int count = GetCount(inTeam); if( count > BestCount ) { BestCount = count ; record(); } return ; } // 第 i 個村民進入衛隊 if(CanIn(dep)) { inTeam[dep]=1; if( (GetCount(inTeam)+(n-dep)) > BestCount ) search(dep+1); // 討論 第 i+1 村民進不進 inTeam[dep]=0; } // 第i個村民不進入衛隊 search(dep+1); return ; } int main() { cin>>n>>m; for(int i=0;i<m;i++) // 記錄m個仇恨關係 { int x,y; cin>>x>>y; hate[x][y] = 1 ; hate[y][x] = 1 ; // x 和 y 是仇恨關係 } search(1); // 從居民1開始 cout<<GetCount(BestRecord)<<endl; for(int i=1;i<=n;i++) { cout<<BestRecord[i]<<" "; } return 0; }