【CERC2012】【BZOJ4057】Kingdoms

王国破产模拟
本文介绍了一种使用状态压缩动态规划(状压DP)的方法来解决一个关于王国间经济危机的模拟问题。具体而言,通过计算一系列的经济借贷关系,确定是否能存在一种破产顺序,使得最后仅剩下一个王国经济稳定。

Description

有一些王国陷入了一系列的经济危机。在很多年以前,他们私底下互相借了许多钱。现在,随着他们的负债被揭发,王国的崩溃不可避免地发生了……现在有n个王国,对于每对王国A和B,A欠B的钱被记为d_AB(我们假设有d_BA=-d_AB成立)。如果一个王国入不敷出(即需要支付超过所能获得的钱),它就可能破产。每当一个王国破产,与它相关的所有债务关系都会被去除,无论是正是负。而王国们的破产不是一瞬间完成的,而是第一个王国破产后,接下来可能破产的王国再继续破产,直到剩下的王国经济都是稳定的。不同的结局将取决于谁先破产,尤其是有的结局只会留下一个王国。请你计算,对于每个王国,是否存在一种结局使得该王国是唯一的幸存者。

Input

第一行一个正整数T,表示有T组数据。

每组数据第一行一个正整数n,表示有n个王国,1 <= n <= 20。
接下来n行,每行n个整数,第i行第j个整数表示d_ij,保证有d_ii = 0, d_ij = -d_ji, |d_ij| <= 10^6。
Output

每组数据输出一行,按照升序输出所有可能的王国编号,空格隔开,如果没有一个王国能满足条件,输出一个0。

Sample Input

1

3

0 -3 1

3 0 -2

-1 2 0
Sample Output

1 3

HINT

Source

鸣谢Tjz

状压DP一下
把memset变成手动赋值.赋值区间小了点,顿时从垫底变成了第8蛤蛤蛤

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define GET (ch>='0'&&ch<='9')
#define MAXN 25
using namespace std;
int T,n;
int d[MAXN][MAXN];
int sta[MAXN],top;
bool f[1<<21];
void in(int &x)
{
    char ch=getchar();x=0;int flag=1;
    while (!GET)    flag=(ch=='-')?-1:1,ch=getchar();
    while (GET) x=x*10+ch-'0',ch=getchar();x*=flag;
}
int main()
{
    in(T);
    while (T--)
    {
        in(n);top=0;
        for (int i=0;i<(1<<n);i++)  f[i]=0;
        for (int i=0;i<n;i++)   for (int j=0;j<n;j++)   in(d[i][j]);
        f[0]=1;
        for (int i=0;i<(1<<n);i++)
            if (f[i])
            for (int j=0;j<n;j++)
                if (!(i>>j&1)&&!f[i|(1<<j)])
                {
                    int sum=0;
                    for (int k=0;k<n;k++)   if (!(i>>k&1))  sum-=d[j][k];
                    if (sum<0)  f[i|(1<<j)]=1;
                }
        for (int i=0;i<n;i++)   if (f[((1<<n)-1)^(1<<i)])   sta[++top]=i+1;
        if (!top)   {puts("0");continue;}
        sort(sta+1,sta+top+1);
        for (int i=1;i<=top;i++)    printf(i!=top?"%d ":"%d\n",sta[i]);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值