zoukankan      html  css  js  c++  java
  • [Usaco2008 Nov]mixup2 混乱的奶牛

    题目

    Description

    混乱的奶牛 [Don Piele, 2007] Farmer John的N(4 <= N <= 16)头奶牛中的每一头都有一个唯一的编号S_i (1 <= S_i <= 25,000). 奶牛为她们的编号感到骄傲, 所以每一头奶牛都把她的编号刻在一个金牌上, 并且把金牌挂在她们宽大的脖子上. 奶牛们对在挤奶的时候被排成一支"混乱"的队伍非常反感. 如果一个队伍里所以任意两头相邻的奶牛的编号相差超过K (1 <= K <= 3400), 它就被称为是混乱的. 比如说,当N = 6, K = 1时, 1, 3, 5, 2, 6, 4 就是一支"混乱"的队伍, 但是 1, 3, 6, 5, 2, 4 不是(因为5和6只相差1). 那么, 有多少种能够使奶牛排成"混乱"的队伍的方案呢?

    Input

    • 第 1 行: 用空格隔开的两个整数N和K
    • 第 2..N+1 行: 第i+1行包含了一个用来表示第i头奶牛的编号的整数: S_i

    Output

    第 1 行: 只有一个整数, 表示有多少种能够使奶牛排成"混乱"的队伍的方案. 答案保证是 一个在64位范围内的整数.

    Sample Input

    4 1
    3
    4
    2
    1

    Sample Output

    2
    //两种方法分别是:
    3 1 4 2
    2 4 1 3

    思路

    首先如果状压$dp$ 的用法不熟悉的读者,可以看看;

    $状压dp入门 $

    那么这一题和-传球游戏之最小总代价-简直一模一样;

    这一题有一个限制条件,就是任意两个相邻的奶牛的编号相差超过$m$;

    那么我们设$dp[i][k]$ 表示队伍里以$i$ 结尾状态为 $k$,有多少组成混乱队伍的方案;

    那么初始状态就是 $dp[i][1<<(i-1)]=1$ ;

    转移方程就是 $dp[i][k]+=dp[j][k oplus (1<<(i-1))]$ ;

    代码

    #include<bits/stdc++.h>
    #define re register
    typedef long long ll;
    using namespace std;
    inline ll read()
    {
        ll a=0,f=1; char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
        while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
        return a*f;
    }
    ll n,m;
    ll a[20];
    ll dp[20][1<<20];
    int main()
    {
        n=read(); m=read();//读入 
        for(re ll i=1;i<=n;i++)
            a[i]=read();//读入 
        for(re ll i=1;i<=n;i++)
            dp[i][1<<(i-1)]=1;//初始化 
        for(re ll k=1;k<=(1<<n)-1;k++)//枚举状态 
        for(re ll i=1;i<=n;i++)//枚举结尾的奶牛 
        {
            if(!(k&(1<<(i-1))))//因为转移是dp[i][k] 以 i 结尾,所以集合也要包涵 i 
                continue;
            for(re ll j=1;j<=n;j++)
            {
                if(i==j)//不能从同一个奶牛转移过来 
                    continue;
                if(!(k&(1<<(j-1))))//从 j 转移过来 集合要包涵 j 
                    continue;
                if(abs(a[i]-a[j])>m)//相邻编号相差超过 m,才为混乱的队伍 
                    dp[i][k]+=dp[j][k^(1<<(i-1))];//转移方程 
    //            cout<<i<<" "<<k<<" "<<j<<" "<<dp[i][k]<<endl;
            }
        }
        ll ans=0;
        for(re ll i=1;i<=n;i++)
            ans+=dp[i][(1<<n)-1];//统计以每个奶牛结尾状态的方案数 
        printf("%lld
    ",ans);//输出
        //return 0; 
    }
  • 相关阅读:
    判断浏览器是否安装ActiveX控件
    浏览器判断及IE版本区分
    获取应用程序根目录
    C#读取csv通用类
    office文档转Txt文档
    合理使用.NET异常处理
    iis操作
    vim配置
    Spring的Annotation使用注意
    JdbcTemplate API备忘
  • 原文地址:https://www.cnblogs.com/wzx-RS-STHN/p/13493469.html
Copyright © 2011-2022 走看看