zoukankan      html  css  js  c++  java
  • cogs 1377. [NOI2011] NOI嘉年华 (dp

    题意:给你n个活动的起止时间,要你从中选一些活动在2个会场安排(不能有两个活动在两个会场同时进行),使活动较少的会场活动数最大,以及在某个活动必须选择的前提下,求该答案。

    思路:由于n很小,时间很大,先将时间离散化,num[l][r]表示全部在[l,r]内的活动个数,pre[i][j]表示前i的时间内给一边j个另一边最多有几个,则用1<=k<=i更新pre[i][j]=max(pre[k][j]+num[k][j],pre[k][j-num[k][i]]),第一问答案是min(pre[time][k],k)中的最大值

    第二问,相当于一段区间s[i],t[i]必选,对于l<=s[i],r>=t[i],算出f[l][r] = min(x+y,pre[l][x]+num[l][r]+suf[r][y])中的最大值,x+y关于x,y单增,pre[l][x]+num[l][r]+suf[r][y]关于x,y单减,x,y不会同时变大或变小,所以从小到大枚举x时,y从大到小...

     1 #include<bits/stdc++.h>
     2 #define fo(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout);
     3 using namespace std;
     4 inline int read(){
     5     char ch=getchar();
     6     int res=0,f=1;
     7     while(!isdigit(ch))f^=(ch=='-'),ch=getchar();
     8     while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
     9     return res*f;
    10 }
    11 const int N=405;
    12 int n,s[N],t[N],a[N],cnt,pre[N][N],suf[N][N],f[N][N],num[N][N];
    13 inline void chemx(int &a,int b){
    14     a=a>b?a:b;
    15 }
    16 inline void chemn(int &a,int b){
    17     a=a>b?b:a;
    18 }
    19 #define calc(a,b) (min((a+b),(pre[l][a]+num[l][r]+suf[r][b])))
    20 int main(){
    21     fo("noi2011_show");
    22     n=read();
    23     for(int i=1;i<=n;i++)s[i]=read(),a[++cnt]=s[i],t[i]=read()+s[i],a[++cnt]=t[i];
    24     sort(a+1,a+cnt+1);
    25     cnt=unique(a+1,a+cnt+1)-a-1;
    26     for(int i=1;i<=n;i++){
    27         s[i]=lower_bound(a+1,a+cnt+1,s[i])-a;
    28         t[i]=lower_bound(a+1,a+cnt+1,t[i])-a;
    29         for(int l=1;l<=s[i];l++)
    30             for(int r=t[i];r<=cnt;r++)num[l][r]++;
    31     }
    32     for(int i=1;i<=cnt;i++)
    33         for(int j=1;j<=n;j++)pre[i][j]=suf[i][j]=-1e9;
    34     for(int i=1;i<=cnt;i++)
    35         for(int j=0;j<=num[1][i];j++)
    36             for(int k=1;k<=i;k++){
    37                 chemx(pre[i][j],pre[k][j]+num[k][i]);
    38                 if(j>=num[k][i])chemx(pre[i][j],pre[k][j-num[k][i]]);
    39             }
    40     for(int i=cnt;i;i--)
    41         for(int j=0;j<=num[i][cnt];j++)
    42             for(int k=cnt;k>=i;k--){
    43                 chemx(suf[i][j],suf[k][j]+num[i][k]);
    44                 if(j>=num[i][k])chemx(suf[i][j],max(suf[k][j]+num[i][k],suf[k][j-num[i][k]]));
    45             }
    46     for(int l=1;l<=cnt;l++){
    47         for(int r=l;r<=cnt;r++){
    48             for(int x=0,y=num[r][cnt];x<=num[1][l];x++){
    49                 while(y&&calc(x,y)<=calc(x,y-1))y--;
    50                 chemx(f[l][r],calc(x,y));
    51             }
    52         }
    53     }
    54     int ans=0;
    55     for(int i=1;i<=cnt;i++)for(int j=1;j<=num[1][i];j++)chemx(ans,min(pre[i][j],j));
    56     cout<<ans<<'
    ';
    57     for(int i=1;i<=n;i++){
    58         int res=0;
    59         for(int l=s[i];l;l--)
    60             for(int r=t[i];r<=cnt;r++)
    61             chemx(res,f[l][r]);
    62         cout<<res<<'
    ';
    63     }
    64 }
    View Code
  • 相关阅读:
    C# 时间+三位随机数
    dataGridView加行标识方法与制作
    MySql多列查询
    php 去掉字符串的最后一个字符
    DataTable 排序
    汇编第一个程序 Hello World (初学者与入门)
    C# 获取前一天,明天,本周,上周,本季度等!
    php 字符串中任意添加
    天涯论坛的经典回帖!!!
    系统时间同步
  • 原文地址:https://www.cnblogs.com/wzgg/p/11396590.html
Copyright © 2011-2022 走看看