CERC 2012 A
题意:有一堆人之间有借钱关系,给你一个关系矩阵Aij表示i欠j多少钱。若是有一个人他的总资产是负的,他可以从矩阵中去除和他一行一列的数据都会去除。问可以被最后留下来的那个人可能是那些?
思路:状态压缩dp表示当前状态可不可以达到,每次状态转移都两重循环判断第j个人能不能被去除。若可以标记,一直递推下去就行了。
代码如下:
1 /************************************************** 2 * Author : xiaohao Z 3 * Blog : http://www.cnblogs.com/shu-xiaohao/ 4 * Last modified : 2014-07-04 08:12 5 * Filename : cerc_A.cpp 6 * Description : 7 * ************************************************/ 8 9 #include <iostream> 10 #include <cstdio> 11 #include <cstring> 12 #include <cstdlib> 13 #include <cmath> 14 #include <algorithm> 15 #include <queue> 16 #include <stack> 17 #include <vector> 18 #include <set> 19 #include <map> 20 #define MP(a, b) make_pair(a, b) 21 #define PB(a) push_back(a) 22 23 using namespace std; 24 typedef long long ll; 25 typedef pair<int, int> pii; 26 typedef pair<unsigned int,unsigned int> puu; 27 typedef pair<int, double> pid; 28 typedef pair<ll, int> pli; 29 typedef pair<int, ll> pil; 30 31 const int INF = 0x3f3f3f3f; 32 const double eps = 1E-6; 33 const int LEN = 21; 34 int n, num[LEN][LEN]; 35 bool dp[1<<20]; 36 37 int main() 38 { 39 // freopen("in.txt", "r", stdin); 40 41 int T; 42 cin >> T; 43 while(T--){ 44 cin >> n; 45 memset(dp, false, sizeof dp); 46 for(int i=0; i<n; i++){ 47 for(int j=0; j<n; j++){ 48 cin >> num[i][j]; 49 } 50 } 51 dp[0] = true; 52 for(int i=0; i<(1<<n); i++){ 53 if(dp[i]){ 54 for(int j=0; j<n; j++){ 55 if((i & (1<<j)) == 0) { 56 int sum = 0; 57 for(int k=0; k<n; k++) 58 if((~i)&(1<<k))sum += num[k][j]; 59 if(sum < 0){ 60 dp[i^(1<<j)] = true; 61 } 62 } 63 } 64 } 65 } 66 vector<int> ans; 67 ans.clear(); 68 for(int i=0; i<n; i++){ 69 if(dp[(1<<n)-1-(1<<i)]) ans.PB(i+1); 70 } 71 if(ans.size() == 0){ 72 cout << 0 << endl; 73 continue; 74 } 75 for(int i=0; i<ans.size(); i++){ 76 cout << ans[i]; 77 if(i != ans.size()-1) cout << " "; 78 } 79 cout << endl; 80 } 81 return 0; 82 }
奔跑吧!少年!趁着你还年轻