您的位置:首页 > 其它

noi 2011 noi嘉年华 动态规划

2012-06-17 12:18 369 查看
题意:NOI2011 在吉林大学开始啦!为了迎接来自全国各地最优秀的信息学选手,

吉林大学决定举办两场盛大的 NOI 嘉年华活动,分在两个不同的地点举办。每

个嘉年华可能包含很多个活动,而每个活动只能在一个嘉年华中举办。

现在嘉年华活动的组织者小安一共收到了 n个活动的举办申请,其中第 i 个

活动的起始时间为 Si,活动的持续时间为Ti。这些活动都可以安排到任意一个嘉

年华的会场,也可以不安排。

小安通过广泛的调查发现,如果某个时刻,两个嘉年华会场同时有活动在进

行(不包括活动的开始瞬间和结束瞬间),那么有的选手就会纠结于到底去哪个

会场,从而变得不开心。所以,为了避免这样不开心的事情发生,小安要求不能

有两个活动在两个会场同时进行(同一会场内的活动可以任意进行)。

另外,可以想象,如果某一个嘉年华会场的活动太少,那么这个嘉年华的吸

引力就会不足,容易导致场面冷清。所以小安希望通过合理的安排,使得活动相

对较少的嘉年华的活动数量最大。

此外,有一些活动非常有意义,小安希望能举办,他希望知道,如果第i 个

活动必须举办(可以安排在两场嘉年华中的任何一个),活动相对较少的嘉年华

的活动数量的最大值。

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

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;
#define MAXN 210
pair<int,int> event[MAXN];
int num[MAXN*2][MAXN*2],pre[2*MAXN][MAXN],back[2*MAXN][MAXN],ans[2*MAXN][2*MAXN];
int a[MAXN*2];
map<int,int> home;
int n,m;
void discretization()
{
sort(a+1,a+2*n+1);
int i,j=0;
a[0]=-1;
for(i=1;i<=2*n;i++)
{
if(a[i]!=a[i-1])
j++;
home[a[i]]=j;
}
for(i=1;i<=n;i++)
{
event[i].first=home[event[i].first];
event[i].second=home[event[i].second];
//cout<<event[i].first<<" "<<event[i].second<<endl;
}
m=j;
}
void solve_all()
{
int i,j,k;
memset(num,0,sizeof(num));
memset(pre,0xaf,sizeof(pre));
memset(back,0xaf,sizeof(back));
//cout<<pre[0][0]<<endl;
int ans=0;
pre[0][0]=0;
for(k=1;k<=n;k++)
for(i=0;i<=event[k].first;i++)
for(j=event[k].second;j<=m+1;j++)
num[i][j]++;

for(i=1;i<=m;i++)
for(j=0;j<=n;j++)
{
for(k=0;k<i;k++)
{
pre[i][j]=max(pre[i][j],pre[k][j]+num[k][i]);
if(j>=num[k][i])
pre[i][j]=max(pre[i][j],pre[k][j-num[k][i]]);
}
//cout<<i<<" "<<j<<" "<<pre[i][j]<<endl;
}
back[m+1][0]=0;
for(i=m;i>=1;i--)
for(j=0;j<=n;j++)
{
for(k=i+1;k<=m+1;k++)
{
back[i][j]=max(back[i][j],back[k][j]+num[i][k]);
if(j>=num[i][k])
back[i][j]=max(back[i][j],back[k][j-num[i][k]]);
}
//cout<<i<<" "<<j<<" "<<back[i][j]<<endl;
}
for(j=0;j<=n;j++)
ans=max(ans,min(j,pre[m][j]));
printf("%d\n",ans);
}
int calc(int i,int j,int x,int y)
{
return min(x+y+num[i][j],pre[i][x]+back[j][y]);
}
void solve_part()
{
int i,j,x,y,k;
memset(ans,0,sizeof(ans));
int s=0;
for(i=1;i<=m;i++)
for(j=i;j<=m;j++)
{
y=n;
s=0;
for(x=0;x<=n;x++)
{
for(y;y>0;y--)
{
if(calc(i,j,x,y-1)<calc(i,j,x,y))
break;
}
s=max(s,calc(i,j,x,y));
}
ans[i][j]=s;
}
for(k=1;k<=n;k++)
{
s=0;
for(i=1;i<=event[k].first;i++)
for(j=event[k].second;j<=m;j++)
s=max(s,ans[i][j]);
printf("%d\n",s);
}
}

int main()
{
scanf("%d",&n);
int i;
for(i=1;i<=n;i++)
{
scanf("%d%d",&event[i].first,&event[i].second);
event[i].second+=event[i].first;
a[2*i-1]=event[i].first; a[2*i]=event[i].second;
}
discretization();
solve_all();
solve_part();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: