zoukankan      html  css  js  c++  java
  • 【简●解】[HNOI2005]星际贸易

    【大意】

    太多了,懒得打,贴(LG)的图了。。。

    【分析】

    开始拿到这道题有点慌:怎么限制条件这么多,再读读题。

    注意一个东西,就是贸易额与费用是独立分开的,并且题目保证只有一种方案获得最大贸易额。

    所以我们(dp)也可以分开(dp)

    对于贸易额,每走到一个星球,我可以选择卖或不卖,经典的背包问题,直接(f[i][j]=min{f[i-1][j-A_i]+B_i})

    然后从后往前扫记录决策点的转移,这些星球是必到的,即必定会在该星球上维修。

    现在来看费用。

    (g[i][j])表示到第(i)个星球,剩余反物质燃料为(j)的最小费用,暴力枚举转移点,则有(g[i][j]={g[k][l]+(j-l+2) imes P_i+T_i}(0le k<i,L_i-L_kle L_0,lle j))

    (O(n^4))转移。。。

    然后可推出一个更优的式子:(g[i][j]=min{g[k][j+2]+F_i,g[i][j-1]+P_i})

    (O(n^3))转移。。。

    然后,,,我就嫖题解了。。。。

    噢,原来可以单调队列优化啊,对于每个(j)开一个单调队列,若当前的(i)为必到的星球,就清空队列中所有的元素,然后把(i)放进去。

    (O(n^2))转移!!!

    【Code】

    #include <queue>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define Re register
    using namespace std;
    const int INF = 0x3f3f3f3f;
    const int MAXR = 4000 + 5;
    const int N = 2000 + 5;
    const int M = 2000 + 5;
    inline int read(){
        int f = 1, x = 0; char ch;
        do { ch = getchar(); if (ch == '-') f = -1; } while (ch < '0' || ch > '9');
        do {x = (x << 3) + (x << 1) + ch - '0'; ch = getchar(); } while (ch >= '0' && ch <= '9'); 
        return f * x;
    }
    int n, m, r, L0, maxm, maxr, A[N], B[N], L[N], P[N], F[N], f[N][M], g[N][M], vis[N]; 
    deque <int> Q[MAXR];
    int main(){
    	n = read(), m = read(), r = read(), L0 = read(); 
    	if (r > (n << 1)) r = (n << 1);
        for (int i = 1;i <= n; ++i) {
        	A[i] = read(), B[i] = read(), L[i] = read(), P[i] = read(), F[i] = read();
        	if (L[i] - L[i - 1] > L0) {
        		puts("Poor Coke!");
        		return 0;
        	}
    	}
    	memset(f, 128, sizeof f);
    	f[0][0] = 0;
    	for (int i = 1;i <= n; ++i) {
    		for (int j = 0;j <= m; ++j) {
    			if (f[i - 1][j] >= 0) f[i][j] = f[i - 1][j];
    			if (j >= A[i]) {
    				if (f[i][j] < f[i - 1][j - A[i]] + B[i]) {
    					f[i][j] = f[i - 1][j - A[i]] + B[i];
    				}
    			}
    		}
    	}
    	
    	for (int i = 1;i <= m; ++i) if (f[n][i] > f[n][maxm]) maxm = i; 
    	
    	for (int i = n, val = maxm;i >= 1; --i) {
    		if (val - A[i] >= 0 && f[i][val] == f[i - 1][val - A[i]] + B[i]){
    			vis[i] = 1;
    			val -= A[i];
    		}
    	}
    	
    	memset(g, 0x3f, sizeof g);
    	g[0][r] = 0;
    	Q[r].push_back(0);
    	for (int i = 1;i <= n; ++i) {
    		for (int j = 0;j <= r; ++j) {
    			if (P[i] > 0 && j > 0) {
    				g[i][j] = min(g[i][j], g[i][j - 1] + P[i]);
    			}
    			
    			while (!Q[j].empty() && L[i + 1] - L[Q[j].front()] > L0) Q[j].pop_front();
    			
    			if (!Q[j + 2].empty()) {
    				g[i][j] = min(g[i][j], g[Q[j + 2].front()][j + 2] + F[i]);
    			}
    			
    			if (vis[i]) Q[j].clear();
    			
    			while (!Q[j].empty() && g[Q[j].back()][j] >= g[i][j]) Q[j].pop_back();
    			
    			Q[j].push_back(i);
    		}
    	}
    	for (int i = 1;i <= r; ++i) if (g[n][i] < g[n][maxr]) maxr = i;
    	
    	if (g[n][maxr] == INF) printf("Poor Coke!
    ");
    	else printf("%d %d
    ", f[n][maxm], f[n][maxm] - g[n][maxr]);	
    	
    	return 0;
    }
    
  • 相关阅读:
    所谓的底层问题
    字符流与字节流
    字节和字符,对信息进行编码
    Asp.net和数据库的一些概念
    谈.NET,由编译器开始谈起
    Extjs中的dom,Ext.Element和Ext.Component对象的关系
    WCF和Delphi通信时序列化的问题
    认真的考虑了下领域模型,发现设计是最难的部分。书上的例子各个对象职责划分的不错,可惜能看懂不代表能设计出。
    MS100 [011020]
    MS100[001]
  • 原文地址:https://www.cnblogs.com/silentEAG/p/11433991.html
Copyright © 2011-2022 走看看