EOJ:Mixed Up Cows
Mixed Up Cows
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submits: 95 | Accepted: 28 |
Description
Each of Farmer John's N (4 ≤ N ≤ 16) cows has a unique serial number S_i (1 ≤ S_i ≤ 25,000). The cows are so proud of it that each one now wears her number in a gangsta manner engraved in large letters on a gold plate hung around her ample bovine neck.
Gangsta cows are rebellious and line up to be milked in an order called 'Mixed Up'. A cow order is 'Mixed Up' if the sequence of serial numbers formed by their milking line is such that the serial numbers of every pair of consecutive cows in line differs by more than K (1 ≤ K ≤ 3400). For example, if N = 6 and K = 1 then 1, 3, 5, 2, 6, 4 is a 'Mixed Up' lineup but 1, 3, 6, 5, 2, 4 is not (since the consecutive numbers 5 and 6 differ by 1).
How many different ways can N cows be Mixed Up?
Gangsta cows are rebellious and line up to be milked in an order called 'Mixed Up'. A cow order is 'Mixed Up' if the sequence of serial numbers formed by their milking line is such that the serial numbers of every pair of consecutive cows in line differs by more than K (1 ≤ K ≤ 3400). For example, if N = 6 and K = 1 then 1, 3, 5, 2, 6, 4 is a 'Mixed Up' lineup but 1, 3, 6, 5, 2, 4 is not (since the consecutive numbers 5 and 6 differ by 1).
How many different ways can N cows be Mixed Up?
Input
* Line 1: Two space-separated integers: N and K
* Lines 2..N+1: Line i+1 contains a single integer that is the serial number of cow i: S_i
* Lines 2..N+1: Line i+1 contains a single integer that is the serial number of cow i: S_i
Output
* Line 1: A single integer that is the number of ways that N cows can be 'Mixed Up'. The answer is guaranteed to fit in a 64 bit integer.
Sample Input
4 13421
Sample Output
2
Hint
The 2 possible Mixed Up arrangements are:
3 1 4 2
2 4 1 3
3 1 4 2
2 4 1 3
____________________________________________________________________________________________
题解:
二进制的思想
T[m][i],m是以2进制的数表示当前取了哪些数,i为以当前这些数组成的序列中的最末尾元素的下标如:
下标: 5 4 3 2 1
元素: 8 7 5 4 2
二进制:0 1 0 1 1
m=11
T[9][1]表示的是取了7,4,2这些元素,组成的以2结尾的序列,包括:7 4 2和4 7 2
ans[m][i]就是状态T[m][i]有多少种满足条件的序列
状态转移方程是:ans[m][i]=ans[m/i][j](j为从m中去掉i所形成的集合中与a[i]相差大于k的a[j])这个状态转移方程不难理解,就是当前集合中以a[i]结尾的满足条件的序列个数,等于当前集合除掉a[i]以后的集合拿各种元素做结尾的序列个数之和,这些序列必须保证末尾能插入a[i],所以a[j]与a[i]之差要大于k。
最后我们要求的是所有元素都要用到排成的序列,所以就是ans[(1<<n)-1][j](j=0到n-1)
1<<n表示1左移n位,也就是2^n
判断j是否在m里,可以用m&(1<<j)是否等于1,因为1<<j表示的是对应于a[j]的那一位二进制1,m&(1<<j)就是看在这一位上m是否为1
同理,把j加入到m里,就是m|(1<<j)
代码:
代码
1 #include<stdio.h>
2 #include<math.h>
3 int i,j,k,n,kk;
4 long long dp[65536][17],ans;
5 int s[17];
6 int main()
7 {
8 scanf("%d%d",&n,&kk);
9 for (i=1;i<=n;i++)
10 scanf("%d",&s[i]);
11 for (i=1;i<=n;i++)
12 dp[1<<(i-1)][i]=1;
13 for (i=0;i<=(1<<n);i++)
14 for (j=1;j<=n;j++)
15 if ((1<<(j-1))&i)
16 for (k=1;k<=n;k++)
17 if (((1<<(k-1))&i)==0&&abs(s[j]-s[k])>kk)
18 dp[i|(1<<(k-1))][k]=dp[i|(1<<(k-1))][k]+dp[i][j];
19 for (i=1;i<=n;i++)
20 ans=ans+dp[(1<<n)-1][i];
21 printf("%ld\n",ans);
22 }