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

状压dp水题

俗话说:能打暴力的都是简单题,因为你可以用暴力来对拍啊!那么只要你足够强,你就能写出一个正解而不出现WA。

暴力做法就是直接枚举全排列,一个一个算即可。

正解是定义dp[i][j]为最后一个元素为\(i\),选中的状态为\(j\)的方案数。转移很显然,太显然了。不说了。

所以最后把\(\sum{dp[i][S]}\)加起来就可以了。


但是,我做状压dp的时候总会有些奇奇怪怪的现象,以至于莫名其妙算不出答案。

这个时候,换一下枚举的顺序!!!

其实我之前也出现过这样的经历,递推顺序错直接爆零,顺序对直接AC

然后我就愉快地AC了。

代码:

#include<cstdio>
#include<algorithm>
#define ll long long
const int maxn = 17, maxN = 65537;
ll dp[maxn][maxN];// 以i为最后一位,状态为j的方案数 
ll a[maxn];
int n, m;
int S;

void init()
{
    for(int i = 1; i <= n; i++) dp[i][1 << (i - 1)] = 1;
}
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
    init();
    S = (1 << n) - 1;
    for(int j = 1; j <= S; j++)
    {
        for(int i = 1; i <= n; i++)
        {
            if((1 << (i - 1)) & j)
            {
                for(int k = 1; k <= n; k++)
                {
                    if((1 << (k - 1)) & j) continue;
                    if(abs(a[i] - a[k]) > m) dp[k][j | (1 << (k - 1))] += dp[i][j];
                }
            }
        }
    }
    ll ans = 0;
    for(int i = 1; i <= n; i++) ans += dp[i][S];
    printf("%lld\n", ans);
    return 0;
}
posted @ 2018-10-28 21:57  Garen-Wang  阅读(89)  评论(0编辑  收藏  举报