zoukankan      html  css  js  c++  java
  • POJ 1821 Fence

    http://poj.org/problem?id=1821

    题目

    有n块木板排成一行,有k个工人,第$i$个工人坐在第$s_i$块木板处,每刷一块木板的工钱是$p_i$,他只能选择粉刷长度不超过$l_i$,包含$s_i$的连续的一段木板,也可以不粉刷。

    每块木板要么只由一个工人粉刷,要么不粉刷

    问这些工人能得到的工钱的和最大是多少

    $nleqslant16000quad kleqslant100$

    题解

    设dp[i][j]为前i个工人刷了前j块木板

    那么

    $dp[i][j]=dp[i][j-1]$

    $dp[i][j]=dp[i-1][j]$

    $dp[i][j]=max{dp[i-1][k]+(j-k) imes p_i|k<s_i,jgeqslant s_i,j-kleqslant l_i}$

    直接转移,时间复杂度$mathcal{O}(n^2k)$无法接受

    改写一下

    $dp[i][j]=j imes p_i+max{dp[i-1][k]-k imes p_i|j-l_ileqslant k< si}$

    发现max的范围是不断向后移动的,因此可以使用单调队列(滑动窗口)

    那么时间复杂度$mathcal{O}(nk)$

    AC代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<map>
    #define REP(i,a,b) for(register int i=(a); i<(b); i++)
    #define REPE(i,a,b) for(register int i=(a); i<=(b); i++)
    #define PERE(i,a,b) for(register int i=(a); i>=(b); i--)
    using namespace std;
    typedef long long ll;
    int n,m;
    #define MAXN 16007
    #define MAXM 107
    struct node {
    	int l,p,s;
    	bool operator<(const node&r) const {
    		return s<r.s;
    	}
    } a[MAXM];
    int dp[MAXM][MAXN];
    int dw[MAXN], di[MAXN];
    int main() {
    	scanf("%d%d", &n, &m);
    	REP(i,1,m) scanf("%d%d%d", &a[i].l, &a[i].p, &a[i].s);
    	sort(a+1,a+1+m);
    	//dp[i][j] = k<si, j>=si, j-k<=li max(dp[i-1][k]+p*(j-k)) (]
    	//dp[i][j] = j-li<=k<=si max(dp[i-1][k]-p*k)+p*j;
    	//dp[i][j] = dp[i-1][j]
    	//dp[i][j] = dp[i][j-1]
    	memset(dp[0],0,sizeof(dp[0]));
    	REPE(i,1,m) {
    		int l=0,r=0;
    		REP(k,max(a[i].s-a[i].l,0), a[i].s) {
    			int t=dp[i-1][k]-a[i].p*k;
    			while(r>l && dw[r-1]<t) r--;
    			dw[r]=t;
    			di[r]=k;
    			r++;
    		}
    //]		int mj=min(a[i].l+a[i].s, n);____
    		dp[i][0]=0;
    		REPE(j,1,n) {
    			dp[i][j]=max(dp[i][j-1], dp[i-1][j]);
    			if(j>=a[i].s) {
    				int t=j-a[i].l; while(l<r && di[l]<t) l++;
    				if(l<r) dp[i][j]=max(dp[i][j], dw[l]+a[i].p*j);
    			}
    		}
    	}
    	printf("%d
    ", dp[m][n]);
    }
    
  • 相关阅读:
    HTTP断点续传 规格严格
    Java Shutdown 规格严格
    linux 命令源码 规格严格
    JTable调整列宽 规格严格
    linux 多CPU 规格严格
    Hello can not find git path 规格严格
    Kill 规格严格
    拜拜牛人 规格严格
    Swing 规格严格
    Debugging hangs in JVM (on AIX but methodology applicable to other platforms) 规格严格
  • 原文地址:https://www.cnblogs.com/sahdsg/p/12551492.html
Copyright © 2011-2022 走看看