package A类有价值的回顾的;
//http://www.tuicool.com/articles/JVzMVj
import java.util.Scanner;
//如果一道题前期你没有明确的思路,说明你已经输了,而且后期你脱的时间越长,输的越多
//不要纠结在毫不值得的地方
public class 状态压缩 {
public static int mod = 100000000;
public static void main (String[] args){
Scanner sc = new Scanner(System.in);
int M = sc.nextInt();
int N = sc.nextInt();//每一行都变成一个二进制数来表示
int[] a = new int[M];//这里输入的是本身条件的限制
boolean[] c = new boolean[1<<N];//记录第i种方案是否可行 这里除去与a[]中矛盾的剩下的就是所有可行的方案
//但是相比于前期的求出所有可行方案,不如在后期判断的时候加进去限制条件,固定的思维模式在一定条件下是可以的,你要做到的是利益的最大化,而不是你内心的成就感
int[][] dp = new int[M][1<<N];
//输入条件限制
for(int i=0;i<M;i++){//无论从第几个开始都可以做,那么就不要较劲非要找到一种统一方法,把你的劲使到最优的地方去
for(int j=0;j<N;j++){
int b = sc.nextInt();
if(b == 1)
a[i] += 1<<(N-j-1);
}
}
//找到一行中所有左右不相邻的方案,对于每一行都适用
for(int i=0;i<c.length;i++){
if((i&i<<1) == 0)
c[i] = true;
}
//初始化第零行
for(int i=0;i<c.length;i++){
if(c[i] == true &&(~a[0]&i) == 0)//记住1&1才有判断性
//里面的()必须要加,等于1说明前后相邻且为1 !!!记住:!=1的反面不是==0
dp[0][i] = 1;
}
//往接下来的第j行,本行的i方案,有几种
for(int j=1;j<M;j++){
for(int i=0;i<(1<<N);i++){
for(int prei=0;prei<(1<<N);prei++){//prei指的是前一行的i方案
//前后不相邻 左右不相邻 条件允许
if((i&prei)==0 && (~a[j]&i) == 0 && c[i] == true){
dp[j][i] = (dp[j][i] + dp[j-1][prei])%mod;因为这里只与前一个有关系 ,可以用滚动数组
}
}
}
}
//计算最后一次的
int sum = 0;
for(int i=0;i<(N<<1);i++){
sum = (sum + dp[M-1][i])%mod;
}
System.out.println(sum);
}
}
/*
* 题目大意: 农夫有一块地,被划分为m行n列大小相等的格子,其中一些格子是可以放牧的(用1标记),农夫可以在这些格子里放牛,
其他格子则不能放牛(用0标记),并且要求不可以使相邻格子都有牛。现在输入数据给出这块地的大小及可否放牧的情况,
求该农夫有多少种放牧方案可以选择(注意:任何格子都不放也是一种选择,不要忘记考虑!
Sample Input
2 3
1 1 1
0 1 0
Sample Output
9
*/
状态压缩.java
最新推荐文章于 2024-05-21 13:57:10 发布