noi 2011 noi嘉年华 动态规划

题意:NOI2011 在吉林大学开始啦!为了迎接来自全国各地最优秀的信息学选手,
吉林大学决定举办两场盛大的 NOI 嘉年华活动,分在两个不同的地点举办。每
个嘉年华可能包含很多个活动,而每个活动只能在一个嘉年华中举办。
现在嘉年华活动的组织者小安一共收到了 n个活动的举办申请,其中第 i 个
活动的起始时间为 Si,活动的持续时间为Ti。这些活动都可以安排到任意一个嘉
年华的会场,也可以不安排。
小安通过广泛的调查发现,如果某个时刻,两个嘉年华会场同时有活动在进
行(不包括活动的开始瞬间和结束瞬间),那么有的选手就会纠结于到底去哪个
会场,从而变得不开心。所以,为了避免这样不开心的事情发生,小安要求不能
有两个活动在两个会场同时进行(同一会场内的活动可以任意进行)。
另外,可以想象,如果某一个嘉年华会场的活动太少,那么这个嘉年华的吸
引力就会不足,容易导致场面冷清。所以小安希望通过合理的安排,使得活动相
对较少的嘉年华的活动数量最大。
此外,有一些活动非常有意义,小安希望能举办,他希望知道,如果第i 个
活动必须举办(可以安排在两场嘉年华中的任何一个),活动相对较少的嘉年华
的活动数量的最大值。

http://blog.sina.com.cn/s/blog_86942b140101557q.html

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<map>
  6 #include<algorithm>
  7 using namespace std;
  8 #define MAXN 210
  9 pair<int,int> event[MAXN];
 10 int num[MAXN*2][MAXN*2],pre[2*MAXN][MAXN],back[2*MAXN][MAXN],ans[2*MAXN][2*MAXN];
 11 int a[MAXN*2];
 12 map<int,int> home;
 13 int n,m;
 14 void discretization()
 15 {
 16     sort(a+1,a+2*n+1);
 17     int i,j=0;
 18     a[0]=-1;
 19     for(i=1;i<=2*n;i++)
 20     {
 21         if(a[i]!=a[i-1])
 22             j++;
 23         home[a[i]]=j;
 24     }
 25     for(i=1;i<=n;i++)
 26     {
 27         event[i].first=home[event[i].first];
 28         event[i].second=home[event[i].second];
 29         //cout<<event[i].first<<" "<<event[i].second<<endl;
 30     }
 31     m=j;
 32 }
 33 void solve_all()
 34 {
 35     int i,j,k;
 36     memset(num,0,sizeof(num));
 37     memset(pre,0xaf,sizeof(pre));
 38     memset(back,0xaf,sizeof(back));
 39     //cout<<pre[0][0]<<endl;
 40     int ans=0;
 41     pre[0][0]=0;
 42     for(k=1;k<=n;k++)
 43         for(i=0;i<=event[k].first;i++)
 44             for(j=event[k].second;j<=m+1;j++)
 45                 num[i][j]++;
 46 
 47     for(i=1;i<=m;i++)
 48     for(j=0;j<=n;j++)
 49     {
 50         for(k=0;k<i;k++)
 51         {
 52             pre[i][j]=max(pre[i][j],pre[k][j]+num[k][i]);
 53             if(j>=num[k][i])
 54                 pre[i][j]=max(pre[i][j],pre[k][j-num[k][i]]);
 55         }
 56         //cout<<i<<" "<<j<<" "<<pre[i][j]<<endl;
 57     }
 58     back[m+1][0]=0;
 59     for(i=m;i>=1;i--)
 60     for(j=0;j<=n;j++)
 61     {
 62         for(k=i+1;k<=m+1;k++)
 63         {
 64             back[i][j]=max(back[i][j],back[k][j]+num[i][k]);
 65             if(j>=num[i][k])
 66                 back[i][j]=max(back[i][j],back[k][j-num[i][k]]);
 67         }
 68     //cout<<i<<" "<<j<<" "<<back[i][j]<<endl;
 69     }
 70     for(j=0;j<=n;j++)
 71         ans=max(ans,min(j,pre[m][j]));
 72     printf("%d\n",ans);
 73 }
 74 int calc(int i,int j,int x,int y)
 75 {
 76     return min(x+y+num[i][j],pre[i][x]+back[j][y]);
 77 }
 78 void solve_part()
 79 {
 80     int i,j,x,y,k;
 81     memset(ans,0,sizeof(ans));
 82     int s=0;
 83     for(i=1;i<=m;i++)
 84     for(j=i;j<=m;j++)
 85     {
 86         y=n;
 87         s=0;
 88         for(x=0;x<=n;x++)
 89         {
 90             for(y;y>0;y--)
 91             {
 92                 if(calc(i,j,x,y-1)<calc(i,j,x,y))
 93                     break;
 94             }
 95             s=max(s,calc(i,j,x,y));
 96         }
 97         ans[i][j]=s;
 98     }
 99     for(k=1;k<=n;k++)
100     {
101         s=0;
102         for(i=1;i<=event[k].first;i++)
103         for(j=event[k].second;j<=m;j++)
104             s=max(s,ans[i][j]);
105         printf("%d\n",s);
106     }
107 }                
108 
109 
110 int main()
111 {
112     scanf("%d",&n);
113     int i;
114     for(i=1;i<=n;i++)
115     {
116         scanf("%d%d",&event[i].first,&event[i].second);
117         event[i].second+=event[i].first;
118         a[2*i-1]=event[i].first; a[2*i]=event[i].second;
119     }
120     discretization();
121     solve_all();
122     solve_part();
123     return 0;
124 }

转载于:https://www.cnblogs.com/myoi/archive/2012/06/17/2552523.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值