[cerc2012][Gym100624A]20181013

 

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\n",i+1);
49             }
50         if(!bk) printf("0\n");
51     }
52     return 0;
53 }

 

posted @ 2018-10-18 11:29  拦路雨偏似雪花  阅读(186)  评论(0编辑  收藏  举报