zoukankan      html  css  js  c++  java
  • poj 1821 Fence 单调队列优化dp

    /* poj 1821 n*n*m 暴力*/
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 110
    #define maxm 16010
    using namespace std;
    int n,m,f[maxn][maxm],ans;
    struct node{
        int l,s,p;
        bool operator < (const node &x) const {
            return s<x.s;
        }
    }a[maxn];
    int max(int x,int y){
        return x>y?x:y;
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m)){
            for(int i=1;i<=m;i++)
                scanf("%d%d%d",&a[i].l,&a[i].p,&a[i].s);
            memset(f,0,sizeof(f));ans=0;
            sort(a+1,a+1+m);//排序s为关键字 
            for(int i=1;i<=m;i++){//状态表示 前i个人 干到j这里 的最优值 
                int x=min(n,a[i].s+a[i].l-1);//i最多干到哪 
                for(int j=1;j<=n;j++){
                    f[i][j]=max(f[i][j-1],f[i-1][j]);//i不干j 可以是j-1的状态 也可以是上一个人干到j的状态 
                    if(j<a[i].s||j>x)continue;//i必须停在这个范围里 也就是状态在这个范围 
                    for(int k=0;k<a[i].s;k++){//上一个人 i-1 他不能把i的起点覆盖了 否则i就走不了了 
                        if(j-k>a[i].l)continue;//i要把k-j的都盖了 长度有限制 
                        f[i][j]=max(f[i][j],f[i-1][k]+(j-k)*a[i].p);
                    }
                    ans=max(ans,f[i][j]);
                }    
            }
            printf("%d
    ",ans);
        }
        
        return 0;
    }
    /* 
    poj 1821 单调队列优化
    wa到挺了.....
    一开始队列指针写错了...
    好吧平时用STL最近手打在改习惯改乱了.
    开始一直混乱着
    不知道怎么保证队列里存的是i-1的状态而不是i的
    根据方程的含义来看 上次不能盖了这次的s 这次还至少到s
    正好分开了 多以存的时候分开
    第一个for是存i-1的状态
    后一个是更新i 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 110
    #define maxm 16010
    using namespace std;
    int n,m,f[maxn][maxm],ans;
    int q[maxm],head,tail;
    struct node{
        int l,s,p;
        bool operator < (const node &x) const {
            return s<x.s;
        }
    }a[maxn];
    int max(int x,int y){
        return x>y?x:y;
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m)){
            for(int i=1;i<=m;i++)
                scanf("%d%d%d",&a[i].l,&a[i].p,&a[i].s);
            memset(f,0,sizeof(f));ans=0;
            sort(a+1,a+1+m);
            for(int i=1;i<=m;i++){
                head=1;tail=0;
                for(int j=1;j<=n;j++)
                    f[i][j]=max(f[i-1][j],f[i][j-1]);
                int L=max(0,a[i].s-a[i].l);
                int R=min(n,a[i].s+a[i].l-1);
                for(int j=L;j<a[i].s;j++){
                    int x=f[i-1][j]-j*a[i].p;
                    while(head<=tail&&f[i-1][q[tail]]-q[tail]*a[i].p<x)tail--;
                    q[++tail]=j;
                }
                for(int j=a[i].s;j<=R;j++){
                    while(head<=tail&&j-q[head]>a[i].l)head++;
                    int y=q[head];
                    f[i][j]=max(f[i][j],f[i-1][y]+(j-y)*a[i].p);//这里要取大 
                    ans=max(ans,f[i][j]);
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Team--时代团队第一次团队项目---基于大作业的思考
    敏捷软件开发
    求一个二维数组的最大子矩阵
    电梯调度分析(二)
    一个简单算法的设计(一个数组中连续区间和的最大值)
    电梯调度算法(-)
    "top k"问题的深入探讨
    js中判断对象是否为空的方法
    Spring Security 3.x 完整入门教程
    Filter 过滤器
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/5970132.html
Copyright © 2011-2022 走看看