码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 4664: Count

时间:2017-06-17 19:27:55      阅读:137      评论:0      收藏:0      [点我收藏+]

标签:ros   scanf   continue   printf   表示   efi   space   soft   const   

这道题和bzoj上一道叫魔法碰撞的题很像,只不过做法更加巧妙了。

一开始的想法是$f[i][j][k][0/1/2]$表示后i个数有j段当前混乱程度为k的方案,最后一维表示边界还能放几个。

转移的时候枚举每个数是山峰山谷或者中间的数,然后让混乱程度加上$h$或减去$h$.

但是这样做第三维的状态数太大了。

转变思路,从小到大枚举i,让第三维的意义变为当前每一段中的数两两之间的混乱度加上之后合并完所有段后至少会产生的混乱度。

每次$k=k+(j*2+l-2)*(h[i+1]-h[i])$,就是现在每个空的代价会加上$(h[i+1]-h[i])$,现在放$h[i+1]$的时候不会产生新的代价。

这样第三维就是递增的了,最大就是L。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 105
using namespace std;
const int p = 1000000007;
int n,L;
int h[N];
int f[2][105][1205][3];
int main()
{
//  freopen("count.in","r",stdin);
//  freopen("count.out","w",stdout);
    scanf("%d%d",&n,&L);
    for(int i=1;i<=n;i++)scanf("%d",&h[i]);
    sort(h+1,h+n+1);
    if(h[n]-h[1]>L)
    {
        puts("0");return 0;
    }
    if(n==1)
    {
        puts("1");
        return 0;
    }
    // f[i][j][k][0] 前i个数被分成了j段混乱度是k
    int now=0,pre=1;
    f[0][1][0][1]=2;
    f[0][1][0][2]=1;
    for(int i=1;i<n;i++)
    {
        now^=1;pre^=1;
        memset(f[now],0,sizeof(f[now]));
        // 处理i+1 
        for(int j=1;j<=i;j++)
        {
            for(int k=0;k<=L;k++)
            {
                for(int l=0;l<=2;l++)
                {
                    if(f[pre][j][k][l])
                    {
                        int tmp=f[pre][j][k][l];
                        int tp=k+(h[i+1]-h[i])*(2*j+l-2);
                        if(tp>L)continue;
                        if(l)
                        {
                            (f[now][j][tp][l-1]+=1LL*tmp*l%p)%=p;
                            (f[now][j+1][tp][l-1]+=1LL*tmp*l%p)%=p;
                        }
                        (f[now][j-1][tp][l]+=1LL*tmp*(j-1)%p)%=p;
                        (f[now][j+1][tp][l]+=1LL*tmp*(j-1+l)%p)%=p;
                        (f[now][j][tp][l]+=1LL*tmp*(2*j-2+l)%p)%=p;
                    }
                }
            }
        }
    }
    int ans=0;
    for(int i=0;i<=L;i++)
    {
        ans+=f[now][1][i][0];
        ans%=p;
    }
    printf("%d\n",ans);
    return 0;
}

  

 

bzoj 4664: Count

标签:ros   scanf   continue   printf   表示   efi   space   soft   const   

原文地址:http://www.cnblogs.com/ezyzy/p/7040888.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!