德玛西亚万岁(状压dp)

德玛西亚万岁

https://ac.nowcoder.com/acm/problem/15034

由于状压dp是在位运算的基础上进行的,所以先了解一下一些基础的位运算操作
我们把每一行的状态用二进制储存起来

    ll x=read();
        a[i]=(a[i]<<1)+x;

假如输入的是101
那么a[i]的变化过程为
a[i]=1
a[i]=2
a[i]=5
5的二进制刚好是101
解决了储存问题,在解决图上冲突问腿
有一个二进制数字x

if(x&x<<1)

可以判断是否有相邻的两者相同
还有一种冲突是当前状态j和地图状态不符合
假如地图状态(第i行)a[i]=1011
j1=1100(不合法)
j2=1000(合法)

那么j1&a[i]=1000
j2&a[i]=1000
所以我们可以用

    if((j&a[i])!=j) continue;

判断当前状态是否和地图状态冲突
上下两行的状态冲突判断比较简单
不能同时为1 ,(对于某一位)

    if(k&j) continue;

代码

#include <map>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <cstdio>
#include <bitset>
#include <vector>
#include <iomanip>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define UpMing main
#define re register
#pragma GCC optimize(2)
#define Accept return 0;
#define lowbit(x) ((x)&(-(x)))
#define mst(x, a) memset( x,a,sizeof(x) )
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dep(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef unsigned long long ull;
const int inf =0x3f3f3f3f;
const int maxn=5e5+7;
const ll mod = 100000000;
const int N =1e6+3;
inline ll read() {
    ll  x=0;
    bool f=0;
    char ch=getchar();
    while (ch<'0'||'9'<ch)    f|=ch=='-', ch=getchar();
    while ('0'<=ch && ch<='9')
        x=x*10+ch-'0',ch=getchar();
    return f?-x:x;
}
void out(ll x) {
    int stackk[20];
    if(x<0) {
        putchar('-');
        x=-x;
    }
    if(!x) {
        putchar('0');
        return;
    }
    int top=0;
    while(x) stackk[++top]=x%10,x/=10;
    while(top) putchar(stackk[top--]+'0');
}
ll n,m,dp[16][30000],a[16];
int UpMing() {
    while(scanf("%lld%lld",&n,&m)!=EOF) {
        mst(a,0);
        for(int i=1 ; i<=n ; i++)
            for(int j=0 ; j<m ; j++) {
                ll x=read();
                a[i]=(a[i]<<1)+x;
            }
        mst(dp,0);
        dp[0][0]=1;

        for(int i=1 ; i<=n ; i++) {
            for(int j=0 ; j<(1<<m); j++) {
                if((j&a[i])!=j) continue;
                if(j&(j<<1))  continue;
                for(int k=0 ; k<(1<<m); k++) {
                    if(k&j) continue;
                    dp[i][j]+=dp[i-1][k]%mod,dp[i][j]%=mod;
                }
            }
        }
        ll res=0;
        for(int i=0 ; i<(1<<m); i++)
            res+=dp[n][i]%mod,res%=mod;
        out(res);
        puts(" ");
    }
    Accept;
}
/*

*/
全部评论

相关推荐

只写bug的程序媛:才15,我招行20多万,建设银行50多万,说放弃就放弃
点赞 评论 收藏
分享
找不到工作死了算了:没事的,雨英,hr肯主动告知结果已经超越大部分hr了
点赞 评论 收藏
分享
评论
1
收藏
分享
牛客网
牛客企业服务