4525: [Cerc2012]Kingdoms

4525: [Cerc2012]Kingdoms

题意

  n个国家,两两之间可能存在欠债或者被欠债的关系,一个国家破产:其支出大于收入。问一个国家能否坚持到最后。

思路

  很有意思的一道题。

  dp[s]表示在当前国家存在情况为s,1-存活,0-破产。那么起始为11111...。然后枚举一个国家,判断是否可以破产,转移。

  最后,扫一遍所有只有1的情况。

代码

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5  
 6 using namespace std;
 7 
 8 const int N = 30;
 9 int d[N][N],f[(1<<21)+10];
10 
11 inline int read() {
12     int x = 0,f = 1;char ch = getchar();
13     for (; !isdigit(ch); ch=getchar()) if(ch=='-') f=-1;
14     for (; isdigit(ch); ch=getchar()) x = x*10+ch-'0';
15     return x*f; 
16 }
17 
18 int main() {
19     int T = read();
20     while (T--) {
21         int n = read();
22         for (int i=1; i<=n; ++i) 
23             for (int j=1; j<=n; ++j) 
24                 d[i][j] = read();
25         int MaxS = (1<<n)-1; 
26         for (int i=0; i<=MaxS; ++i) f[i] = false;
27         f[MaxS] = true;
28         for (int s=MaxS; s>=1; --s) {
29             if (!f[s]) continue;
30             int ans = 0;
31             for (int i=1; i<=n; ++i) {
32                 if (!(s&(1<<(i-1)))) continue;
33                 int sum = 0 ;
34                 for (int j=1; j<=n; ++j) 
35                     if (s&(1<<(j-1))) sum += d[j][i]; //j欠i=>i可以获得的 
36                 if (sum < 0) f[s^(1<<(i-1))] = true; 
37             }
38         }
39         bool flag = true;
40         for (int i=1; i<=n; ++i) {
41             if (f[(1<<(i-1))]) {
42                 if (flag) printf("%d",i),flag = false;
43                 else printf(" %d",i);
44             }
45         }
46         if (flag) printf("0");
47         puts(""); 
48     }
49     return 0;
50 }
原文地址:https://www.cnblogs.com/mjtcn/p/8977074.html