1. 程式人生 > >bzoj[Usaco2008 Nov]mixup2 混亂的奶牛 狀壓dp

bzoj[Usaco2008 Nov]mixup2 混亂的奶牛 狀壓dp

pos pac time medium man geo += str color

[Usaco2008 Nov]mixup2 混亂的奶牛

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 1204 Solved: 698
[Submit][Status][Discuss]

Description

混亂的奶牛 [Don Piele, 2007] Farmer John的N(4 <= N <= 16)頭奶牛中的每一頭都有一個唯一的編號S_i (1 <= S_i <= 25,000). 奶牛為她們的編號感到驕傲, 所以每一頭奶牛都把她的編號刻在一個金牌上, 並且把金牌掛在她們寬大的脖子上. 奶牛們對在擠奶的時候被排成一支"混亂"的隊伍非常反感. 如果一個隊伍裏任意兩頭相鄰的奶牛的編號相差超過K (1 <= K <= 3400), 它就被稱為是混亂的. 比如說,當N = 6, K = 1時, 1, 3, 5, 2, 6, 4 就是一支"混亂"的隊伍, 但是 1, 3, 6, 5, 2, 4 不是(因為5和6只相差1). 那麽, 有多少種能夠使奶牛排成"混亂"的隊伍的方案呢?

Input

* 第 1 行: 用空格隔開的兩個整數N和K

* 第 2..N+1 行: 第i+1行包含了一個用來表示第i頭奶牛的編號的整數: S_i

Output

第 1 行: 只有一個整數, 表示有多少種能夠使奶牛排成"混亂"的隊伍的方案. 答案保證是 一個在64位範圍內的整數.

Sample Input

4 1
3
4
2
1

Sample Output

2

輸出解釋:

兩種方法分別是:
3 1 4 2
2 4 1 3
題解:設f[i][j]表示以第i個奶牛結尾,奶牛的選擇狀態為j的方案數。 轉移方程也比較簡單 f[k][(1<<(k-1))|j]+=f[i][j];(abs(a[k]-a[i])>K,(1<<(k-1))|j!=j,(1<<(i-1))&j!=0)
初始令f[i][1<<i]=1即可。
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring> 
 5 using namespace std;
 6 int n,kk,p[20],a[20],maxx;
 7 long long f[20][1<<16],ans;
 8 int main(){
 9   scanf("%d%d",&n,&kk);maxx=(1<<n)-1
; 10 for(int i=1;i<=n;i++){scanf("%d",&a[i]);p[i]=1<<(i-1);} 11 for (int i=1;i<=n;i++)f[i][p[i]]=1; 12 for (int i=0;i<=maxx;i++) 13 for (int j=1;j<=n;j++) 14 if (p[j]&i) 15 for (int k=1;k<=n;k++) 16 if ((p[k]|i)!=i&&abs(a[k]-a[j])>kk) f[k][p[k]|i]+=f[j][i]; 17 for (int i=1;i<=n;i++) ans+=f[i][maxx]; 18 cout<<ans<<endl; 19 }

bzoj[Usaco2008 Nov]mixup2 混亂的奶牛 狀壓dp