USACO 2008 Nov Gold 1.Mixed Up Cows

描述:
Each of Farmer John's N (4 <= N <= 16) cows has a unique serial number S_i (1 <= S_i <= 25,000). The cows are so proud of it that each one now wears her number in a gangsta manner engraved in large letters on a gold plate hung around her ample bovine neck.

Gangsta cows are rebellious and line up to be milked in an order called 'Mixed Up'. A cow order is 'Mixed Up' if the sequence of serial numbers formed by their milking line is such that the serial numbers of every pair of consecutive cows in line differs by more than K (1 <= K <= 3400). For example, if N = 6 and K = 1 then 1,3, 5, 2, 6, 4 is a 'Mixed Up' lineup but 1, 3, 6, 5, 2, 4 is not (since the consecutive numbers 5 and 6 differ by 1).

How many different ways can N cows be Mixed Up?

输入:
* Line 1: Two space-separated integers: N and K

* Lines 2..N+1: Line i+1 contains a single integer that is the serial
        number of cow i: S_i

输出:
* Line 1: A single integer that is the number of ways that N cows can
        be 'Mixed Up'. The answer is guaranteed to fit in a 64 bit
        integer.

样例输入:
4 1
3
4
2

1


样例输出:

2

题意:

给出n个数,组成一个每两个数之间相差必须大于m的排列;

求这样的排列有多少个;

题解:

n<=16的范围,很可能是状压或搜索之类的算法;

考虑组成这样子的排列,下一个数是什么仅由其上一个的大小决定;

那么就可以设状态为f[i][j],其中i是目前排列的结尾数的序号;

j为表示n个数中取了哪些的状态(因为j里面已经包括了个数所以就不需要再列出来个数了);

判断两个数是否相邻我用了邻接矩阵。。;

然后转移好像有点麻烦,写成dfs感觉好写多了;


代码:


#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 20
using namespace std;
typedef long long ll;
int n,m,a[N],can[N][65555];
ll f[N][65555];
bool map[N][N];
ll dfs(int d,int now,int pre)
{
    if(f[pre][now])
    {
        return f[pre][now];
    }
    if(d==n)
    {
        return 1;
    }
    int i;
    ll ret=0;
    for(i=1;i<=n;i++)
    {
        if(map[pre][i]&&(now&(1<<i))==0)
        ret+=(f[i][now|(1<<i)]=dfs(d+1,now|(1<<i),i));
    }
    return ret;
}
int main()
{
    int i,j,k;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
        scanf("%d",a+i);
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            if(abs(a[i]-a[j])>m)
                map[i][j]=1;
    for(i=0;i<=n;i++)
        map[0][i]=1,map[i][0]=1;
    printf("%lld",dfs(0,0,0));
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值