BZOJ2454 : TopCoder SRM 463 RabbitPuzzle

Claris發表於2016-10-24

每種狀態最多隻有三種後繼狀態:中間往左跳,中間往右跳,兩邊往中間跳。

如果把它們分別看成左兒子、右兒子、父親的話,那麼會得到一些二叉樹。

取出起始狀態和終止狀態往上跳$k$步的所有狀態,其他狀態我們只關心它們到關鍵狀態的距離。

於是設$dp[i][j][k]$表示從起始狀態跳了$i$步,目前位於狀態$j$子樹內距離$j$深度為$k$的狀態的方案數,然後DP即可。

時間複雜度$O(k^3)$。

 

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=110,P=1000000007;
struct E{
  long long v[3];
  void read(){
    scanf("%lld%lld%lld",&v[0],&v[1],&v[2]);
    sort(v,v+3);
  }
  E left(){
    E b;
    for(int i=0;i<3;i++)b.v[i]=v[i];
    b.v[1]=b.v[0]*2-b.v[1];
    swap(b.v[0],b.v[1]);
    return b;
  }
  E right(){
    E b;
    for(int i=0;i<3;i++)b.v[i]=v[i];
    b.v[1]=b.v[2]*2-b.v[1];
    swap(b.v[1],b.v[2]);
    return b;
  }
  bool can(){
    return v[0]+v[2]!=v[1]*2;
  }
  E up(){
    E b;
    for(int i=0;i<3;i++)b.v[i]=v[i];
    if(v[1]-v[0]<v[2]-v[1]){
      b.v[0]=b.v[1]*2-b.v[0];
      swap(b.v[0],b.v[1]);
    }else{
      b.v[2]=b.v[1]*2-b.v[2];
      swap(b.v[1],b.v[2]);
    }
    return b;
  }
  bool operator==(const E&b){return v[0]==b.v[0]&&v[1]==b.v[1]&&v[2]==b.v[2];}
}S,T,now,a[N<<1];
int K,n,i,j,k,t,son[N<<1][2],f[N<<1],dp[N][N<<1][N];
inline void up(int&x,int y){x+=y;if(x>=P)x-=P;}
inline int id(E b){
  for(int i=1;i<=n;i++)if(a[i]==b)return i;
  return 0;
}
inline void push(E b){if(!id(b))a[++n]=b;}
int main(){
  S.read();
  T.read();
  scanf("%d",&K);
  for(push(now=S),i=1;i<=K;i++){
    if(!now.can())break;
    push(now=now.up());
  }
  for(push(now=T),i=1;i<=K;i++){
    if(!now.can())break;
    push(now=now.up());
  }
  for(i=1;i<=n;i++){
    son[i][0]=id(a[i].left());
    son[i][1]=id(a[i].right());
    if(a[i].can())f[i]=id(a[i].up());
  }
  dp[0][id(S)][0]=1;
  for(i=0;i<K;i++)for(j=1;j<=n;j++)for(k=0;k<=K;k++)if(dp[i][j][k]){
    for(t=0;t<2;t++)if(k)up(dp[i+1][j][k+1],dp[i][j][k]);
    else{
      if(son[j][t])up(dp[i+1][son[j][t]][0],dp[i][j][k]);
      else up(dp[i+1][j][1],dp[i][j][k]);
    }
    if(k)up(dp[i+1][j][k-1],dp[i][j][k]);
    else if(f[j])up(dp[i+1][f[j]][0],dp[i][j][k]);
  }
  return printf("%d",dp[K][id(T)][0]),0;
}

  

相關文章