TC SRM 638 DIV1 600 NarrowPassage2

Problem Statement

在一个狭长的通道中有$n$只狼,每只狼的体积为$size_i$,如果相邻的两只狼体积不超过$m$,则可以交换位置,求可以有多少种排列。

$n≤50,1≤m≤1,000,000,000$

Tutorial

每次选出区间中体积最大的狼,如果其他狼可以越过它,那么即可在整个区间里自由移动,而不能越过它的狼则被隔离到两个区间里,可以分治

区间总共有$n$只狼,能自由移动的狼个数为$cnt$,那么最后结果等于$$solve(l)*solve(r)*A_{n}^{cnt}$$

 

给定一些拓扑关系然后统计一些信息的题,算上这题最近遇到3道:
Permutation,结构是树,但因为要统计逆序对数比较烦,树形dp

局部极小值,因为是网格,而且标记的是局部极小值,所以可以通过确定较少的点状压dp计算结果

 

关于本题,我想到的部分

首先,可以在区间内畅通无阻的狼可以随便取一个位置

然后一个点如果两边的点都过不去,就可以分成2个子问题

因为“两边的点都过不去”这个条件并不清晰,所以我放弃了分治这个思路

正解利用了区间体积最大这个性质实现了分治

路曼曼其修远兮……

局部极小值和本题都有一个类似DAG的模型,所以我开始都试着往图论+dp的方向想==

现在我可以得到一个简洁的结论 DAG拓扑排序的结果有多少种可能 是NP问题

应该可以帮助以后少走一些弯路吧

还有关于拓扑问题的突破口其实也很简单:最值

然后就是挖性质、玩套路的本事了==

 1 #include <set>
 2 #include <ctime>
 3 #include <queue>
 4 #include <cstdio>
 5 #include <bitset>
 6 #include <cctype>
 7 #include <bitset>
 8 #include <cstdlib>
 9 #include <cassert>
10 #include <cstring>
11 #include <iostream>
12 #include <algorithm>
13 #define inf (1<<30)
14 #define INF (1ll<<62)
15 #define fi first
16 #define se second
17 #define rep(x,s,t) for(register int x=s,t_=t;x<t_;++x)
18 #define per(x,s,t) for(register int x=t-1,s_=s;x>=s_;--x)
19 #define travel(x) for(int I=last[x],to;I&&(to=e[I].to);I=e[I].nxt)
20 #define prt(x) cout<<#x<<":"<<x<<" "
21 #define prtn(x) cout<<#x<<":"<<x<<endl
22 #define pb(x) push_back(x)
23 #define hash asfmaljkg
24 #define rank asfjhgskjf
25 #define y1 asggnja
26 #define y2 slfvm
27 using namespace std;
28 typedef long long ll;
29 typedef pair<int,int> ii;
30 template<class T>void nt(T x){
31     if(!x)return;
32     nt(x/10);
33     putchar(x%10+'0');
34 }
35 template<class T>void pt(T x){
36     if(x<0)putchar('-'),x=-x;
37     if(!x)putchar('0');
38     else nt(x);
39 }
40 template<class T>void ptn(T x){
41     pt(x);putchar('\n');
42 }
43 template<class T>void pts(T x){
44     pt(x);putchar(' ');
45 }
46 template<class T>inline void Max(T &x,T y){if(x<y)x=y;}
47 template<class T>inline void Min(T &x,T y){if(x>y)x=y;}
48 
49 const int maxn=55;
50 const int mod=1000000007;
51 class NarrowPassage2 {
52 public:
53     ll cnk[maxn][maxn],fac[maxn];
54     int m;
55     int solve(vector<int>d){
56         if(d.size()<=1)return 1;
57         int n=d.size();
58         int v=-1,id;
59         rep(i,0,n){
60             if(d[i]>v){
61                 v=d[i];
62                 id=i;
63             }
64         }
65         vector<int>l,r;
66         int cnt=0;
67         rep(i,0,id){
68             if(d[i]+v<=m)cnt++;
69             else l.pb(d[i]);
70         }
71         rep(i,id+1,n){
72             if(d[i]+v<=m)cnt++;
73             else r.pb(d[i]);
74         }
75         return (ll)solve(l)*solve(r)%mod*cnk[n][cnt]%mod*fac[cnt]%mod;
76     }
77     int count(vector<int>d, int maximum) {
78         cnk[0][0]=fac[0]=1;
79         rep(i,1,d.size()+1)
80             fac[i]=fac[i-1]*i%mod;
81         rep(i,0,d.size()+1){
82             rep(j,1,i)cnk[i][j]=(cnk[i-1][j-1]+cnk[i-1][j])%mod;
83             cnk[i][0]=cnk[i][i]=1;
84         }
85         m=maximum;
86         return solve(d);
87     }
88 };

 

posted @ 2016-08-15 22:06  ShinFeb  阅读(201)  评论(0编辑  收藏  举报