HDU 3811 Permutation(状态压缩+记忆化搜索)

Permutation

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 559    Accepted Submission(s): 259


 

Problem Description

In combinatorics a permutation of a set S with N elements is a listing of the elements of S in some order (each element occurring exactly once). There are N! permutations of a set which has N elements. For example, there are six permutations of the set {1,2,3}, namely [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], and [3,2,1]. 
But Bob think that some permutations are more beautiful than others. Bob write some pairs of integers(Ai, Bi) to distinguish beautiful permutations from ordinary ones. A permutation is considered beautiful if and only if for some i the Ai-th element of it is Bi. We want to know how many permutations of set {1, 2, ...., N} are beautiful.

 

Input

The first line contains an integer T indicating the number of test cases.
There are two integers N and M in the first line of each test case. M lines follow, the i-th line contains two integers Ai and Bi.

Technical Specification
1. 1 <= T <= 50
2. 1 <= N <= 17
3. 1 <= M <= N*N
4. 1 <= Ai, Bi <= N

 

Output

For each test case, output the case number first. Then output the number of beautiful permutations in a line.

 

Sample Input

 

3 3 2 1 1 2 1 3 2 1 1 2 2 4 3 1 1 1 2 1 3

 

Sample Output

 

Case 1: 4 Case 2: 3 Case 3: 18

题意:给你n(n<=17)和m(m<=n*n),接下来n对数(xi,yi)

定义一个1~n的全排列是完美的,设为a1,a2,...,an,存在xi,使a(xi)=yi

思路:由于n比较小,我们利用二进制状态压缩表示1~n哪个数已经选了。然后进行记忆化搜索即可。

代码:

#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(register int i=(a);i<=(b);++i)
#define dep(i,a,b) for(register int i=(a);i>=(b);--i)
using namespace std;
const int maxn=18;
int n,m,k,mm;
ll tmp,cnt,ans;
bool c[maxn][maxn];
ll dp[(1<<17)+5][2];
ll dfs(int i,int zt,int fg)
{
    if(i==n+1&&zt==mm) return fg;
    else if(i==n+1||zt==mm) return 0;
    if(dp[zt][fg]!=-1) return dp[zt][fg];
    ll sum=0;
    rep(j,0,n-1)
    if(!(zt&(1<<j))){
        int x=(fg|c[i][j+1]);
        sum+=dfs(i+1,zt|(1<<j),x);
    }
    dp[zt][fg]=sum;
    return dp[zt][fg];
}
int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        memset(dp,-1,sizeof(dp));
        memset(c,0,sizeof(c));
        scanf("%d%d",&n,&m);
        mm=(1<<n)-1;
        rep(i,0,m-1)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            c[x][y]=1;
        }
        ll ans=dfs(1,0,0);
        printf("Case %d: %lld\n",cas++,ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/LSD20164388/article/details/89278332