AtCoder Beginner Contest 273 F - Hammer 2(离散化&&dp)

题意:

从原点开始,到目标点 t a r g e t target target
求最少的路程。
有n个锤子,n个墙
h [ i ] h[i] h[i] i i i个锤子的位置
w [ i ] w[i] w[i] i i i面墙的位置
i i i面墙只能被第 i i i个锤子打碎

思路:

  • 有负数点,先离散化。
  • 考虑dp
    d p 1 [ x ] [ y ] dp1[x][y] dp1[x][y]区间 [ x , y ] [x,y] [x,y]最后到左端点x的最小距离。
    d p 2 [ x ] [ y ] dp2[x][y] dp2[x][y]区间 [ x , y ] [x,y] [x,y]最后到右端点y的最小距离。
  • 转移时,要考虑 x − 1 x-1 x1 y + 1 y+1 y+1是否是墙,如果是墙,是否拿到了锤子。
    d p 1 [ x − 1 ] [ y ] dp1[x-1][y] dp1[x1][y]:
    d p 2 [ x ] [ y + 1 ] dp2[x][y+1] dp2[x][y+1]

AC(JAVA)

package com.hgs.atcoder.abc.contest273.f;

/**
 * @author youtsuha
 * @version 1.0
 * Create by 2022/10/15 19:52
 */
import java.util.*;
import java.io.*;
public class Main {
    static FastScanner cin;
    static PrintWriter cout;

    private static void init()throws IOException {
        cin = new FastScanner(System.in);
        cout = new PrintWriter(System.out);
    }

    private static void close(){
        cout.close();
    }
    static int lower_bound(List<Integer> ax, int v){
        int L = 0, R = ax.size() - 1;
        while(L < R){
            int mid = L + R + 1 >> 1;
            // a[mid] <= v
            if(ax.get(mid).compareTo(v) <= 0) L = mid;
            else R = mid - 1;
        }
        return L;
    }
    private static void sol()throws IOException {
        int n = cin.nextInt(), target = cin.nextInt();
        int w[] = new int[n+1];
        int h[] = new int[n+1];
        List<Integer> ax = new ArrayList<>();
        ax.add(0);ax.add(target);
        for(int i = 1; i <= n; i ++ ) {
            w[i] = cin.nextInt();
            ax.add(w[i]);
        }
        for(int i = 1; i <= n; i ++ ) {
            h[i] = cin.nextInt();
            ax.add(h[i]);
        }

        ax = new ArrayList<>(new TreeSet<>(ax));

        int p0 = lower_bound(ax,0);
        int sz = ax.size() - 1;
        int w2h[] = new int[sz+1];
        int isWall[] = new int[sz+1];
        for(int i = 1; i <= n; i ++ ) {
            w[i] = lower_bound(ax,w[i]);
            h[i] = lower_bound(ax,h[i]);
            w2h[w[i]] = h[i];
            isWall[w[i]] = 1;
        }

        long dp1[][] = new long[sz+3][sz+3];//left:X
        long dp2[][] = new long[sz+3][sz+3];//right:y
        long inf = (long) 1e18;
//        for(int i = 0; i <= sz; i ++ ) for(int j = 0; j <= sz; j ++ ) dp1[i][j] = dp2[i][j] = Long.MAX_VALUE;
        for(int i = 0; i <= sz; i ++ ) for(int j = 0; j <= sz; j ++ ) dp1[i][j] = dp2[i][j] = inf;
        dp1[p0][p0] = dp2[p0][p0] = 0;

        target = lower_bound(ax,target);
        long ans = inf;
        for(int x = p0; x >= 0; x-- ){
            for(int y = p0; y <= sz; y ++ ) {
                if(x <= target && target <= y) {
                    ans = Math.min(ans, dp1[x][y]);
                    ans = Math.min(ans, dp2[x][y]);
                }
                if(x-1 >= 0) {
                    if(isWall[x-1] == 1 && w2h[x-1] >= x && w2h[x-1] <= y || isWall[x-1] == 0) {
                        dp1[x-1][y] = Math.min(dp1[x-1][y], dp1[x][y] + Math.abs(ax.get(x - 1) - ax.get(x)));
                        dp1[x-1][y] = Math.min(dp1[x-1][y], dp2[x][y] + Math.abs(ax.get(x - 1) - ax.get(y)));
                    }
                }
                if(y + 1 <= sz){
                    if(isWall[y+1] == 1 && w2h[y+1] >= x && w2h[y+1] <= y || isWall[y+1] == 0) {
                        dp2[x][y+1] = Math.min(dp2[x][y+1], dp1[x][y] + Math.abs(ax.get(x) - ax.get(y+1)));
                        dp2[x][y+1] = Math.min(dp2[x][y+1], dp2[x][y] + Math.abs(ax.get(y) - ax.get(y+1)));
                    }
                }
            }
        }
        cout.println(inf == ans?-1:ans);
    }
    public static void main(String[] args) throws IOException {
        init();
        sol();
        close();
    }
}
class FastScanner {
    BufferedReader br;
    StringTokenizer st = new StringTokenizer("");

    public FastScanner(InputStream s) {
        br = new BufferedReader(new InputStreamReader(s));
    }

    public FastScanner(String s) throws FileNotFoundException {
        br = new BufferedReader(new FileReader(new File(s)));
    }

    public String next() throws IOException {
        while (!st.hasMoreTokens()){
            try {
                st = new StringTokenizer(br.readLine());
            } catch (IOException e) { e.printStackTrace(); }
        }
        return st.nextToken();
    }

    public int nextInt() throws IOException {
        return Integer.parseInt(next());
    }

    public long nextLong() throws IOException {
        return Long.parseLong(next());
    }

    public double nextDouble() throws IOException {
        return Double.parseDouble(next());
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值