您的位置:首页 > 其它

2018年全国多校算法寒假训练营练习比赛(第二场) F

2018-03-14 21:42 369 查看
首先附上题目链接
我先讲一下题目是思路、n * m的输入、、最大为12* 12的因为要枚举所有的可能性、所以,1 << 12 * 1 << 12的代价不绝对通过不了、在这里使用的是状态dp、 通过二进制表示的形式来解决 、也就是  12 * (1 << 12)、 
首先要找出所有的站位的可能性、用于接下来的枚举、然后通过位操作、(判断找出)每一组都不与站位要求冲突、(比如 0不能站人)上下也不会在一起、、 应该就差不多了吧、具体的看代码吧、import java.util.Scanner;

public class Main {
static final int MOD = 100000000;
static int [] a = new int [13]; // 最初初始的状态、、
static int [] nextState = new int [1 << 12];
static int [][] dp = new int [13][1 << 12];
static int num = 0;
static int n, m;
public static void main(String[] args) {
Scanner input = new Scanner(System.in);

while(input.hasNext()){
Init(); // 初始化、 一定要记得初始化(多组输入)
n = input.nextInt();
m = input.nextInt();
int tmp;
for(int i = 1; i <= n; i++){
for(int j = m - 1; j >= 0; j--){
tmp = input.nextInt();
a[i] |= (tmp << j);
}
}
int len = 0;
for(int i = 0; i < (1 << 12); i++){
if((i & (i << 1)) == 0){ // 说明没有站在一起的、、
nextState[len++] = i;
if((i | a[1]) == a[1]){ // 说明不该站人的地方没有站人、 这个站位可以、
dp[1][i]++;
}
}
}
int state1, state2;
for(int i = 2; i <= n; i++){
for(int j = 0; j < len; j++){ // 所有站位的可能性 (隔壁不能站人的那种、、)
state1 = nextState[j];
if((state1 | a[i]) == a[i]) { // 不该站人的地方没有站人、 可以哈、、
for(int k = 0; k < len; k++){
state2 = nextState[k];
if((state2 & state1) == 0) {// 说明上下没有靠近在一起、、
dp[i][state1] = (dp[i][state1] + dp[i - 1][state2]) % MOD; // state1是当前状态的位置、 state2 是上一个状态的位置、
}
}
}

}
}
num = 0;
for(int i = 0; i < len; i++){
num = (num + dp
[nextState[i]]) % MOD;
}
System.out.println(num);
}
}

private static void Init(){
for(int i = 0; i < 13; i++){
a[i] = 0;
for(int j = 0; j < (1 << 12); j++){
dp[i][j] = 0;
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐