码迷,mamicode.com
首页 > 其他好文 > 详细

状态压缩

时间:2020-04-15 11:15:17      阅读:63      评论:0      收藏:0      [点我收藏+]

标签:lang   ==   ++   main   分配   一个   c++   输入   状态   

P1879 [USACO06NOV]玉米田Corn Fields

农场主John新买了一块长方形的新牧场,这块牧场被划分成M行N列(1 ≤ M ≤ 12; 1 ≤ N ≤ 12),每一格都是一块正方形的土地。John打算在牧场上的某几格里种上美味的草,供他的奶牛们享用。

遗憾的是,有些土地相当贫瘠,不能用来种草。并且,奶牛们喜欢独占一块草地的感觉,于是John不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边。

John想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供他选择?(当然,把新牧场完全荒废也是一种方案)

输入输出格式

输入格式:
第一行:两个整数M和N,用空格隔开。

第2到第M+1行:每行包含N个用空格隔开的整数,描述了每块土地的状态。第i+1行描述了第i行的土地,所有整数均为0或1,是1的话,表示这块土地足够肥沃,0则表示这块土地不适合种草。

输出格式:
一个整数,即牧场分配总方案数除以100,000,000的余数。

int main(){
    cin >> n >> m;
    int t;

    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= m; j++){
            cin >> t;
            map[i] = (map[i] << 1) + t;
        }
    }

    int state = 1 << m;
    //  处理状态i是否合法
    for (int i = 0; i < state; i++){
        if ( ( (i << 1) & i)  == 0 && ( ( (i >> 1) & i) == 0 )  )
            can[i] = 1;
    }

    // f[i][j] 表示前i行,且第i行的状态为j的方案数
    for (int i = 0; i < state; i++){
        if (can[i] && ( i & map[1] ) == i ){
            f[1][i] = 1;
        }    
    }

    for (int i = 2; i <= n; i++){
        for (int j = 0; j < state; j++){
            // 如果j是一个合法的状态
            if (can[j] && (j & map[i]) == j){
                for (int k = 0; k < state; k++){
                    // 如果上一行的状态j与i不冲突
                    if ( (k & j) == 0){
                        f[i][j] = (f[i][j] + f[i - 1][k]) % mod;
                    }
                }
            }
        }
    }
    long long ans = 0;
    for (int i = 0; i < state; i++)
        ans = (ans + f[n][i]) % mod;
    cout << ans;
}

状态压缩

标签:lang   ==   ++   main   分配   一个   c++   输入   状态   

原文地址:https://www.cnblogs.com/keik/p/12703557.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!