A
题意:n(n<=20)个国家,每个国家之间有一些债务关系,总体为负债的国家会破产,破产国家的债务关系全部消除。问哪些国家可能成为最后一个唯一存在的国家。
题解:
对于每一个状态,面对若干个负债国,哪个国家先破产会影响最后的结果。
考虑到n<=20,可以状压。f[s]表示状态为s(0表示未破产,1表示已破产)是否存在。
转移方程:if(!s&(1<<i) && i在s状态下已破产) f[s+(1<<i)] | = f[s];
O(2^n * n^2)//很慢www谁有更好的方法请留言
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<queue> 6 using namespace std; 7 8 const int N=50; 9 int n,a[N][N],ok[N],f[1100000]; 10 11 int main() 12 { 13 //freopen("a.in","r",stdin); 14 int T; 15 scanf("%d",&T); 16 while(T--) 17 { 18 scanf("%d",&n); 19 for(int i=0;i<n;i++) 20 for(int j=0;j<n;j++) 21 scanf("%d",&a[i][j]); 22 23 memset(f,0,sizeof(f)); 24 f[0]=1; 25 for(int s=0;s<(1<<n);s++) 26 { 27 if(!f[s]) continue; 28 for(int i=0;i<n;i++) 29 { 30 if(!(s&(1<<i))) 31 { 32 int sum=0; 33 for(int j=0;j<n;j++) 34 if(!(s&(1<<j))) sum-=a[i][j]; 35 if(sum<0) f[s|(1<<i)]=1; 36 } 37 } 38 } 39 memset(ok,0,sizeof(ok)); 40 int bk=0,now=0; 41 for(int i=0;i<n;i++) 42 if(f[((1<<n)-1)-(1<<i)]) ok[i]=1,bk++; 43 for(int i=0;i<n;i++) 44 if(ok[i]) 45 { 46 now++; 47 if(now<bk) printf("%d ",i+1); 48 else printf("%d ",i+1); 49 } 50 if(!bk) printf("0 "); 51 } 52 return 0; 53 }