题目链接:
https://cn.vjudge.net/problem/Kattis-busplanning
题目大意:
自己翻译
具体思路:
问的别的,不是我的思路,,
二进制枚举这n个人的子集,判断哪几个状态是能够在一辆车上的,然后对于所有状态判断他的哪两个互补的子集能使得这个状态的人最少。
记录每个状态是有哪些子集构成的,便于输出。
vis[i]代表i状态的一个子集是什么
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define inf 0x3f3f3f3f 5 #define LL_inf (1ll << 60) 6 const int maxn = 1e6 + 100; 7 const int mod = 1e9 + 7; 8 vector<int>Edge[maxn]; 9 map<string,int>sto; 10 map<int,string>un_sto; 11 int dp[maxn]; 12 int n,k,c; 13 int vis[maxn]; 14 map<int,int>q; 15 int cal(int sta) 16 { 17 q.clear(); 18 vector<int>tmp; 19 for(int i=0; i<n; i++) 20 { 21 if((1ll<<i)&sta) 22 tmp.push_back(i),q[i]=1; 23 } 24 if(tmp.size()>c)return inf ; 25 int len=tmp.size(); 26 for(int i=0; i<len; i++) 27 { 28 for(int j=0; j<Edge[tmp[i]].size(); j++) 29 { 30 if(q[Edge[tmp[i]][j]]) 31 { 32 return inf ; 33 } 34 } 35 } 36 return 1; 37 } 38 void dfs(int u) 39 { 40 if(dp[u]==1)// 如果这个子集可以放在一个车上 41 { 42 for(int i=0; i<n; i++) 43 { 44 if((1<<i)&u) 45 cout<<un_sto[i]<<" "; 46 } 47 cout<<endl; 48 return ; 49 } 50 dfs(u^vis[u]);// 按照他的子集往下搜 51 dfs(vis[u]); 52 } 53 int main() 54 { 55 string str; 56 cin>>n>>k>>c; 57 for(int i=0; i<n; i++) 58 { 59 cin>>str; 60 sto[str]=i; 61 un_sto[i]=str; 62 } 63 string str1,str2; 64 for(int i=1; i<=k; i++) 65 { 66 cin>>str1>>str2; 67 Edge[sto[str1]].push_back(sto[str2]); 68 Edge[sto[str2]].push_back(sto[str1]); 69 } 70 int maxstate=(1ll<<n)-1; 71 for(int i=0; i<=maxstate; i++) 72 { 73 dp[i]=cal(i); 74 } 75 for(int i=0; i<=maxstate; i++) 76 { 77 for(int j=i; j; j=(j-1)&i) // 枚举子集 78 { 79 if(dp[i]>dp[i^j]+dp[j]) 80 { 81 dp[i]=dp[i^j]+dp[j]; 82 vis[i]=j; 83 } 84 } 85 } 86 cout<<dp[maxstate]<<endl; 87 dfs(maxstate); 88 }