状态压缩、枚举、(dp就是暴力优化过来的)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Poj_1185 {
static int dp[][][] = new int[105][70][70]; // dp 数组、、、
static int base[] = new int[105]; // 用二进制记录初始状态
static int state[] = new int[70]; // 炮兵放置的所有可能(假设都是平原的状态下)
static int soldier[] = new int[70]; // 所有的状态能摆放的状态、、、
static int row, col, nums; // 行列 以及 每一行能摆放的状态的炮兵数量、、、
static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
public static int nextInt() throws IOException {
in.nextToken();
return (int) in.nval;
}
public static String next() throws IOException {
in.nextToken();
return (String) in.sval;
}
public static void main(String[] args) throws IOException {
nums = 0;
row = nextInt();
col = nextInt();
for (int i = 0; i < row; i++) {
String s = next();
for (int k = 0; k < col; k++) {
if (s.charAt(k) == 'H') {
base[i] += (1 << k);
}
}
}
/* for(int i = 0; i < row; i++){
out.println(base[i]);
}
out.flush();*/
for (int i = 0; i < 1 << col; i++) { // 枚举每一种状态 (平地的情况)
if ((i & (i << 1)) != 0 || (i & i << 2) != 0) {
continue;
}
int k = i;
while (k > 0) {
soldier[nums] += (k & 1);
k >>= 1;
}
state[nums++] = i;
}
/* for(int i = 0; i < nums; i++){
out.print(soldier[i] + " ");
}
out.println();*/
for (int i = 0; i < nums; i++) { // 初始化第一行的情况、、、
if ((state[i] & base[0]) != 0) {
continue;
}
dp[0][i][0] = soldier[i];
}
for (int i = 0; i < nums; i++) { // 初始化第二行的情况、、、
if ((state[i] & base[1]) != 0) {
continue;
}
for (int j = 0; j < nums; j++) {
if ((state[j] & state[i]) != 0 || (state[j] & base[0]) != 0) {
continue;
}
dp[1][i][j] = Math.max(dp[1][i][j], dp[0][j][0] + soldier[i]);
}
}
for (int i = 2; i < row; i++) { // 对接下来的各行放置情况进行枚举
for (int k = 0; k < nums; k++) { // 枚举 第 i行的状态、、、
if ((state[k] & base[i]) != 0) {
continue;
}
for (int k1 = 0; k1 < nums; k1++) { // i - 1 的状态、、、
if ((state[k1] & base[i - 1]) != 0 || (state[k] & state[k1]) != 0) {
continue;
}
for (int k2 = 0; k2 < nums; k2++) {
if ((state[k2] & base[i - 2]) != 0
|| (state[k2] & state[k1]) != 0
|| (state[k2] & state[k]) != 0) { // 和当前的状态不兼容、 和上一行的状态不兼容、 和上上行的状态不兼容、
continue;
}
dp[i][k][k1] = Math.max(dp[i][k][k1], dp[i - 1][k1][k2] + soldier[k]); // 当前行 和上一行的状态合并、、、
}
}
}
}
int max = 0;
for (int i = 0; i < nums; i++) {
for (int j = 0; j < nums; j++) {
max = Math.max(max, dp[row - 1][i][j]); // 最后一行的所有可能就是 最多的、遍历一遍、、、
}
}
out.println(max);
out.flush();
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class bailian_4124 {
static int[][] value = new int[1 << 16][16]; // 第一维 代表当前状态(二进制)、第二维 代表当前状态下所在的位置
static int[][] map = new int[16][16]; // 存地图的、、
static int N, minlen;
static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
public static int nextInt() throws IOException {
in.nextToken();
return (int) in.nval;
}
public static String next() throws IOException {
in.nextToken();
return (String) in.sval;
}
public static void main(String[] args) throws IOException {
N = nextInt();
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
map[i][j] = nextInt();
}
}
Init();
dfs(0, 0, 1);
out.println(minlen);
out.flush();
}
public static void Init() {
for (int i = 0; i < 1 << 16; i++) {
for (int j = 0; j < 16; j++) {
value[i][j] = Integer.MAX_VALUE;
}
}
minlen = Integer.MAX_VALUE;
}
public static void dfs(int u, int cur, int k){ // u 当前的位置、 cur 当前的权值、 k 当前已经走过的状态、、、
if(cur > minlen || (u == N - 1) && k < (1 << N) - 1){ // 剪枝、 比当前的状态差、 已经 到最后一个结点 还没有遍历完、、
return;
}
if(value[k][u] <= cur){ // 记忆化搜索 、比当前的状态差、、、
return;
}else{
value[k][u] = cur; // 更新为当前状态
}
if(u == (N - 1) && (k == (1 << N) - 1)){
minlen = Math.min(minlen, cur);
}
for(int v = 0; v < N; v++){
if(map[u][v] != 0 && (k & (1 << v)) == 0){ // 不是自己、 这个点没有到达过、、
dfs(v, cur + map[u][v], k | (1 << v));
}
}
}
}