• 洛谷 P2915 [USACO08NOV]奶牛混合起来Mixed Up Cows 解题报告


    P2915 [USACO08NOV]奶牛混合起来Mixed Up Cows

    题意:

    给定一个长(N)的序列,求满足任意两个相邻元素之间的绝对值之差不超过(K)的这个序列的排列有多少个?

    范围:

    (0<=n<=16,0<=序列元素<=25000,0<=k<=3400)


    统计次数一般是递推干的事情,但是我们发现,这个递推并没有一个很明显的顺序关系,并不可以说前几个转移到下一个之类的。

    看看数据这么小,一般都是状压干的事情了。

    我们可以按照规模进行递推,即一个大小为多少的子序列往后推。层次关系为小的子序列推大的子序列。

    (dp[i][j])代表子序列状态为(i),最后一个元素为原数列的第(j)号元素时的方案数。

    则状态转移:
    (dp[i][j]=sum dp[k][l]),右边是可能的合法转移。

    因为直接枚举子集会有很多无用状态,所以我们采用记忆化搜索来找到合法转移。


    Code:

    #include <cstdio>
    #include <cstring>
    #define ll long long
    ll dp[1<<16][17],s[17],n,k;
    ll abs(ll x){return x>0?x:-x;}
    void init()
    {
        scanf("%lld%lld",&n,&k);
        for(int i=1;i<=n;i++)
            scanf("%lld",s+i);
        memset(dp,-1,sizeof(dp));
        for(int i=1;i<=n;i++)
            dp[1<<n-i][i]=1;
    }
    ll dfs(ll sta,ll las)
    {
        if(~dp[sta][las])
            return dp[sta][las];
        dp[sta][las]=0;
        for(ll i=1;i<=n;i++)
            if(i!=las&&(sta>>n-i)&1&&abs(s[las]-s[i])>k)
                dp[sta][las]+=dfs(sta&(~(1<<n-las)),i);
        return dp[sta][las];
    }
    int main()
    {
        init();
        ll ans=0;
        for(int i=1;i<=n;i++)
            ans+=dfs((1<<n)-1,i);
        printf("%lld
    ",ans);
        return 0;
    }
    

    2018.7.6

  • 相关阅读:
    事务
    XML小总结
    java中array,arrayList,iterator;
    MariaDB Galera Cluster 部署(如何快速部署 MariaDB 集群)
    RHCE7认证学习笔记17——KickStart安装系统
    CentOS中安装MySQL数据库
    centos下搭建svn服务器端/客户端
    AWS安装CDH5.3-CentOS6.4中关键操作步骤
    AWS安装CDH5.3-CentOS6.4
    [转]Servlet 工作原理解析
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9274391.html
Copyright © 2020-2023  润新知