lightoj 1228 - e-Friends(状压DP)

Social networking web sites are very popular these days. I am not mentioning any names because you know better than me. People do have a lot of e-friends now, "you may not know his real identity but he is your friend". Sometimes, there can be rivalries between people, and thus people gets blocked or deleted. And these rivalries don't have to be necessarily commutative. That means x may think y as his enemy, but y may or may not think so.

However, what if you get the opportunity to see all your e-friends live? Since you like social networks very much, you planned to arrange a get-together with your e-friends. So, you invited n of your e-friends in your home. For simplicity, you numbered them from 1 to n. They were your friends, but rivalries existed amongst many of them. You asked them to form a queue such that they can get food from the table. And you will serve foods one by one. But your friends demanded that, no enemy should be the next person in the queue. That means if x thinks that y is his enemy and x's position in the queue is i, then y's position shouldn't be i-1.

So, it became very complex. That's why you decided to add a dissatisfaction index k if one's demand is not fulfilled. And the total dissatisfaction index is the summation of all the dissatisfaction indexes. Now you know the rivalries and the maximum total dissatisfaction index you may allow, you want to find the total number of possible arrangements.

Input

Input starts with an integer T (≤ 30), denoting the number of test cases.

Each case starts with three integers n (1 ≤ n ≤ 12)k (0 ≤ k ≤ 106) and q (1 ≤ q ≤ 1000) which denotes the number of queries. Then there will be n lines. The ith line contains an integer ti (0 ≤ ti < n)and ids of ti distinct friends. It means ith person thinks the ti listed persons as his enemy. Each of the next q lines contains an integer r (0 ≤ r ≤ 108) denoting the total allowable dissatisfaction index.

Output

For each case, print the case number first. Then for each query, print the total number of arrangements possible not exceeding the given total dissatisfaction index.

Sample Input

Output for Sample Input

1

2 10 2

1 2

0

10

5

Case 1:

2

1

 

输入n,K,q,代表有n个人,下面有n行,第i行的第一个数表示第i个人有x个敌人,如果一个人站在他敌人的后面,就会产生K不满意度。q表示有q个询问,每次询问比X不满意度小的站法有多少种。

dp[i][j][k],i表示队伍状态,j表示最后一个站的是j,k表示有k个不满意的。


#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;

int dp[1<<13][15][15];
int main(void)
{
    int T,n,K,q,i,j,k,l;
    int a[15][15];
    scanf("%d",&T);
    int cas = 1;
    while(T--)
    {
        memset(a,0,sizeof(a));
        memset(dp,0,sizeof(dp));
        scanf("%d%d%d",&n,&K,&q);
        for(i=0;i<n;i++)
        {
            int x,y;
            scanf("%d",&x);
            while(x--)
            {
                scanf("%d",&y);
                a[i][y-1] = 1;
            }
        }
        for(i=0;i<n;i++)
            dp[1<<i][i][0] = 1;
        for(i=0;i<(1<<n);i++)
        {
            int cnt = 0;
            for(j=0;j<n;j++)
                if((1<<j)&i)
                    cnt++;
            for(j=0;j<n;j++)
            {
                if((1<<j)&i == 0)
                    continue;
                for(k=0;k<cnt;k++)
                {
                    for(l=0;l<n;l++)
                    {
                        if((1<<l)&i)
                            continue;
                        dp[i|(1<<l)][l][k+a[l][j]] += dp[i][j][k];
                    }
                }
            }
        }
        printf("Case %d:\n",cas++);
        while(q--)
        {
            int x;
            scanf("%d",&x);
            LL sum = 0;
            for(i=0;i<n;i++)
            {
                for(j=0;j<n;j++)
                {
                    if(j*K>x)
                        break;
                    sum += dp[(1<<n)-1][i][j];
                }
            }
            printf("%lld\n",sum);
        }
    }

    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值