0
点赞
收藏
分享

微信扫一扫

动态规划进阶

水墨_青花 2023-05-19 阅读 105

文章目录

状压dp

小国王

在这里插入图片描述
在这里插入图片描述

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

public class Main{
	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
	static int n = 0, k = 0; //棋盘行数 国王个数
  	static int cnt = 0;  //同一行的合法状态个数
  	static int[] s = new int[1 << 12]; //同一行的合法状态集
  	static int[] num = new int[1 << 12]; //每个合法状态包含的国王数
  	static long[][][] dp = new long[12][144][1 << 12];  //前i行放了j个国王,第i行第a个状态时的方案数
	public static void main(String[] args) throws IOException {
		String[] nk = br.readLine().split(" ");
		n = Integer.parseInt(nk[0]);
		k = Integer.parseInt(nk[1]);
		
		//预处理
		for(int i = 0; i < (1 << n); i++) {
			if((i & i >> 1) == 0) { //不存在相邻的1
				s[cnt++] = i; //保存此合法状态
				for(int j = 0; j < n; j++) {
					num[i] += (i>>j&1); //统计每个合法状态包含1(国王)的个数
				}
			}
		}
		
//		System.out.println(cnt);
//		for(int i = 0; i < cnt; i++) {
//			System.out.println(Integer.toBinaryString(s[i]) + " " +num[s[i]]);
//		}
		
		//DP
		dp[0][0][0] = 1; //不放国王也是一种状态
		for(int i = 1; i <= n + 1; i++) {//枚举行
			for(int j = 0; j <= k; j++) { //枚举国王数
				//枚举国王数
				for(int a = 0; a < cnt; a++) { //枚举第i行合法状态
					for(int b = 0; b < cnt; b++) {
						int c = num[s[a]]; //第i行第a个状态的国王数
						//可以继续放国王,不存在同列的1,不存在斜对角的1
						if((j >= c) && ((s[b] & s[a]) == 0) && ((s[b] & (s[a] << 1)) == 0) && ((s[b]&(s[a]>>1)) == 0)) {
							dp[i][j][a] += dp[i-1][j-c][b];
						}
					}
				}
			}
			
		}
		System.out.println(dp[n+1][k][0]);
		
	}
}

玉米田


在这里插入图片描述
在这里插入图片描述

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

public class Main{
	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
	static int mod = (int) 1e9;
	static int n = 0, m = 0; //
	static int[][] a = new int[15][15];
	static int[] g = new int[15]; //各行土地的状态值
  	static int cnt = 0;  //同一行的合法状态个数
  	static int[] s = new int[1 << 14]; //同一行的合法状态集
  	static long[][] dp = new long[15][1 << 15];  //种植了前i行,第i行第a个状态时的方案数
	public static void main(String[] args) throws IOException {
		String[] nm = br.readLine().split(" ");
		n = Integer.parseInt(nm[0]);
		m = Integer.parseInt(nm[1]);
		//预处理
		for(int i = 1;i <= n; i++) {
			String[] aa = br.readLine().split(" ");
			for(int j = 1; j <= m; j++) {
				a[i][j] = Integer.parseInt(aa[j - 1]);
			}
		}
		
		for(int i = 1; i <= n; i++) {
			for(int j = 1; j <= m; j++) {
				int x = a[i][j];
				g[i] = (g[i] << 1) + x;
			}
			// System.out.println(g[i]);
		}
		for(int i = 0; i < (1 << m); i++) {
			if((i&i >> 1)==0) {
				s[cnt++] = i;//保存一行的合法状态
			}
		}
	
		dp[0][0] = 1;
		for(int i = 1; i <= n + 1; i++) {
			for(int a = 0; a < cnt; a++) { //第i行
				for(int b = 0; b < cnt; b++) { //第i-1行状态
					//a种在可以种的地方,a b没有相邻的1
					if((s[a] & g[i]) == s[a] && (s[a] & s[b]) == 0) {
						dp[i][a] = (dp[i][a] + dp[i-1][b])%mod;
					}
					
				}
			}
		}
		//等价于只在1~n行种植
		System.out.println(dp[n+1][0]);
	}
}

炮兵阵地


在这里插入图片描述

举报

相关推荐

0 条评论