Poj_1185 and 百练_4124

Poj_1185 炮兵阵地

状态压缩、枚举、(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();
    }

百练_4124海贼王伟大之航路

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));
            }
        }
        
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值