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;
}