zoukankan      html  css  js  c++  java
  • 牛客网多校训练 德玛西亚*

    题目描述   来源

    德玛西亚是一个实力雄厚、奉公守法的国家,有着功勋卓著的光荣军史。
    这里非常重视正义、荣耀、职责的意识形态,这里的人民为此感到强烈自豪。
    有一天他们想去制裁邪恶的比尔吉沃特,于是派遣了自己最优秀的战士。
    结果比尔吉沃特领土太小,只有长为n宽为m共计n*m块土地,其中有些土
    地标记为0表示为高山峻岭或者深海湖泊,英雄们无法在其中站立,只有标
    记为1的土地才能容纳一个英雄。德玛西亚的英雄们战斗时有一个特点,他
    们不希望队友站在自己旁边显得很暧昧。请问最多能有多少种安排德玛西
    亚英雄的方法?

    输入描述:

    输入包含多组测试数据;
    每组数据的第一行包含2个整数n和m (n <= 12, m <= 12 ),之间用空格隔开;
    接下来的n行,每行m个数,表示n*m的比尔吉沃特领土。

    输出描述:

    输出一个整数n代表安排应用的方法。
    (答案取膜100000000)
    示例1

    输入

    3 3
    1 1 1
    0 1 1
    1 0 0

    输出

    24
    总结
    1.使用状态压缩,逐行枚举
    2.进行位运算一定不能吝啬括号,因为位运算的优先级实在是太低了
    3.因为m,n的范围很小,所以使用一些复杂度高的算法也没什么关系的
    #include <cstdio>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    #define INF 0x3f3f3f3f//可以用于memset
    int map[13];//map[i]第i行的状态
    long long dp[13][1<<12];//dp[i][j],第1到第i行,并且第i行状态为j时,的安排方法
    int isok[1<<12];//isok[i]指第i个不相邻站立的状态,以后就枚举这些状态
    int main()
    {
        int n,m,k;long long ans;
        while(cin>>n>>m)
        {
            memset(dp,0,sizeof(dp));
            memset(map,0,sizeof(map));
            ans=0;
            for(int i=1;i<=n;i++)
            {
                for(int j=m-1;j>=0;j--)
                {
                    cin>>k;
                    if(k==1)
                        map[i]+=(1<<(j));
                }
            }
            int len=1<<m;int num=0;
            for(int i=0;i<len;i++)//初始化第一行
            {
                if((i&(i<<1))==0)
                {
                    isok[num++]=i;
                    if((i|map[1])==map[1])
                    {
                        dp[1][i]=1;
                    }
                }
            }
            for(int i=2;i<=n;i++)
            {
                for(int j=0;j<num;j++)
                {
                    int a1=isok[j];
                    if((a1|map[i])==map[i])
                    for(int k=0;k<num;k++)
                    {
                        int a2=isok[k];
                        if((a2&a1)==0)
                        dp[i][a1]+=dp[i-1][a2];
                    }
                }
            }
            for(int i=0;i<num;i++)
            {
                 ans+=dp[n][isok[i]];
                 ans%=100000000;
            }
            cout<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    190822——喜欢
    190821——彼岸无岸
    190820——随笔
    BLE——协议层次结构
    190817——肖申克的救赎
    190818——人
    190819——皖北部分村落的变迁史
    【转】vfork 和 fork的区别
    C语言文件操作
    【makefile】symbol <函数> : can't resolve symbol 问题分析
  • 原文地址:https://www.cnblogs.com/carcar/p/8450219.html
Copyright © 2011-2022 走看看