水果游戏-动态规划+索引数

哲秀找到了一个新的游戏。游戏是在横向 W格,竖向H格大小的2维格子上进行。

各格子是用坐标表示。最左下方格子用(1, 1)最右上方的格子用(W, H)表示。

 

哲秀的character可在格子最低下行的任意格子上开始。即,哲秀可以选择开始的格子位置

哲秀的character可以在当前格子上,只能以向上,45度方向的左上45度方向的右上3种方向移动到相邻的格子,每次移动一次,且反复执行如上所述的移动。

 

格子上会有一个水果,当哲秀到达有水果的格子时,会吃到水果。每次吃水果时的满足度有所不同。

当哲秀按照如上一样移动吃水果时,请编写求出可获得的最大满足度之和的程序。

 

如下案例一样,根据虚线表示的方法移动的话,可以吃到最多个数的水果,但满足度之和不是最高。获得满足度之和最高的方法是按照图片中实线表示的方法进行移动。

 

 

[输入]

Input的第一行给出包含的测试用例个数T。

每个测试用例的第一行给出格子的横向大小W,竖向大小 H,水果的个数N。(1 ≤ W ≤ 50, 1 ≤ H ≤ 109 , 1 ≤ N ≤ 200,000)

然后通过N行,每行按照顺序给出各水果位置的横向坐标,竖向坐标,满足度。

横向坐标是1以上W以下,竖向坐标是1以上H以下,满足度是1以上109 以下。水果的位置不会重叠。

 

 

 

[输出]

对各测试用例的答案,每个测试用例输出一行。首先输出#x(x是测试用例号码,从 1开始),隔一个空格后,输出可以获得的最大满足度之和。

 

[输入输出 案例]

(输入)

2

4 5 4

4 4 2

4 5 5

1 1 3

2 5 8

2 3 3

1 1 2

2 2 3

1 3 4

 

(输出)

#1 11

#2 9


package sw.pro;

import java.io.*;
import java.util.*;

class Main {
    static int T, W, H, N, off;
    static Long[] top = new Long[128];
    static Long[] bottom = new Long[128];
    static Long ans;
    static Map<Integer, TreeMap<Integer, Long>> MAP = new TreeMap<>();

    public static void main(String args[]) throws Exception {
        //long start = System.currentTimeMillis();
		//System.setIn(Solution.class.getResourceAsStream("input.txt"));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line;
        StringTokenizer st;
        T= Integer.parseInt(br.readLine());
        for (int t = 1; t <= T; t++) {
            line = br.readLine();
            st = new StringTokenizer(line);
            W = Integer.parseInt(st.nextToken());
            H = Integer.parseInt(st.nextToken());
            N = Integer.parseInt(st.nextToken());
            MAP.clear();
            ans = 0L;

            for (int i = 0; i < N; i++) {
                line = br.readLine();
                st = new StringTokenizer(line);
                Integer w = Integer.valueOf(st.nextToken());
                Integer h = Integer.valueOf(st.nextToken());
                Long s = Long.valueOf(st.nextToken());
                if (!MAP.containsKey(h))
                    MAP.put(h, new TreeMap<Integer, Long>());
                MAP.get(h).put(w, s);
            }
            
            mm();
            System.out.printf("#%d %d\n", t, ans);
        }
        //System.out.printf("Time: %d\n", System.currentTimeMillis() - start);
    }
    
    static void mm(){
        Long[] swap;
        Arrays.fill(top, 0L);
        Arrays.fill(bottom, 0L);
        Integer pre = 0;
        off = 1;
        while (off < W) off <<= 1;

        for (Map.Entry<Integer, TreeMap<Integer, Long>> entry : MAP.entrySet()) {
            Integer i = entry.getKey();
            Integer dh = i - pre;
            Long max;
            TreeMap<Integer, Long> row = entry.getValue();
            for (Integer j = 1; j < W+1; j++) {
                Long val = row.get(j);
                if (val == null)
                    val = 0L;
                if (dh >= W - 1)
                    max = bottom[1];
                else
                    max = getMax(off+j-1-dh, off+j-1+dh);
                top[off + j - 1] = val + max;
            }

            for (int j = off -1; j > 0; j--)
                top[j] = Math.max(top[j<<1], top[(j<<1)+1]);

            pre = i;
            swap = bottom;
            bottom = top;
            top = swap;
        }
        ans = bottom[1];
    }
    
    static Long getMax(int start, int end){
        Long max = 0L;
        if (start < off) start = off;
        if (end > off+W-1) end = off+W-1;
        while (start <= end){
            if ((start & 1) == 1){
                max = Math.max(bottom[start], max);
            }

            if ((end & 1) == 0){
                max = Math.max(bottom[end], max);
            }

            start = (start+1) >> 1;
            end = (end-1) >> 1;

        }
        return max;
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值