zoukankan      html  css  js  c++  java
  • 洛谷 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

  • 相关阅读:
    如何在VIM中编辑并保存退出!!!
    MapReduce---数据清洗
    构建之法阅读笔记03
    人月神话阅读笔记03
    学习进度报告16
    大道至简阅读笔记03
    大道至简阅读笔记02
    个人总结
    大道至简阅读笔记01
    学习进度报告15
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9274391.html
Copyright © 2011-2022 走看看