zoukankan      html  css  js  c++  java
  • POJ 1661 Help Jimmy(递推DP)

    思路:

    1. 每个板子有左右两端, dp[i][0], dp[i][1] 分别记录左右端到地面的时间

    2. 从下到上递推计算, 上一层的板子必然会落到下面的某一层板子上, 或者地面上

    总结:

    1. 计算每个板子的 dp[i][0/1] 仅需考虑该板子的直接前驱即可

    2. 动规的思想并不很明显

    3. 代码中, 两个板子相对位置的判断特别精髓

    4. 将地面和初始状态都抽象成一块板子

    代码:

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    class board {
    public:
    	int x1, x2, h;
    	board(int _x1, int _x2, int _h):x1(_x1), x2(_x2), h(_h){}
    	board() {
    		board(-1,-1,-1);
    	}
    	bool operator <(const board & other) const {
    		return this->h < other.h;
    	}
    };
    
    const int INF = 0X3F3F3F3F;
    const int MAXN = 1010;
    int t, N, X, Y, H, MAX;
    board boards[MAXN];
    int dp[MAXN][2];
    
    int mainFunc() {
    	
    	for(int i = 0; i <= N+1; i ++) {
    		for(int j = i-1; j >= 0; j --) {
    			if(boards[i].x1 >= boards[j].x1 && boards[i].x1 <= boards[j].x2) { // i 的左端可以掉落到 j 上
    				int h = boards[i].h - boards[j].h;
    				if(h > MAX) dp[i][0] = INF;
    				else if (j == 0) dp[i][0] = h;
    				else 
    					dp[i][0] = min(dp[j][0]+boards[i].x1-boards[j].x1, dp[j][1]+boards[j].x2-boards[i].x1) + h;
    				break;
    			}
    		}
    		for(int j = i-1; j >= 0; j --) {
    			if(boards[i].x2 >= boards[j].x1 && boards[i].x2 <= boards[j].x2) { // i 的右端可以掉到 j 上
    				int h = boards[i].h - boards[j].h;
    				if(h > MAX) dp[i][1] = INF;
    				else if(j == 0) dp[i][1] = h;
    				else
    					dp[i][1] = min(dp[j][0]+boards[i].x2-boards[j].x1, dp[j][1]+boards[j].x2-boards[i].x2) + h;
    				break;
    			}
    		}
    	}
    	return dp[N+1][1];
    }
    
    int main() {
    	freopen("E:\Copy\ACM\poj\1661\in.txt", "r", stdin);
    	cin >> t;
    	while(t-- >= 1) {
    		cin >> N >> X >> H >> MAX;
    		for(int i = 0; i < N; i ++) {
    			cin >> boards[i].x1 >> boards[i].x2 >> boards[i].h;
    		}
    		boards[N].x1 = -20010, boards[N].x2 = 20010, boards[N].h = 0;
    		boards[N+1].x1 = X, boards[N+1].x2 = X, boards[N+1].h = H;
    		sort(boards, boards+N+2);
    		// mainFunction
    		cout << mainFunc() << endl;
    	}
    	return 0;
    }
    

      

    update 2014年3月16日10:36:58

    1. 直接前驱可以预处理得到

  • 相关阅读:
    VMware Workstation虚拟机Ubuntu中实现与主机共享(复制和粘贴)
    虚拟机 VMware Workstation12 安装Ubuntu系统
    虚拟机 VMware Workstation12 安装OS X 系统
    ASP.NET Core学习链接
    Java开发中的23种设计模式详解
    C#线程同步的几种方法
    FTP webReq.ContentType异常的处理
    大小端 Big-Endian 与 Little-Endian
    C++:运算符重载函数之"++"、"--"、"[ ]"、"=="的应用
    C++:成员运算符重载函数和友元运算符重载函数的比较
  • 原文地址:https://www.cnblogs.com/xinsheng/p/3447334.html
Copyright © 2011-2022 走看看