2017.8.8 B组模拟

来源:互联网 发布:miss淘宝店网址 编辑:程序博客网 时间:2024/05/16 15:04

第一题

油滴扩展 (Standard IO)

Description

在一个长方型框子里,最多有N(0≤N≤6)个相异的点。在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其它油滴或者框子的边界。必须等一个油滴扩展完毕才能放置下一个油滴。那么应该按照怎样的顺序在这N个点上放置油滴,才能使放置完毕后所有油滴占据的总体积最大呢?(不同的油滴不会相互融合)
注:圆的面积公式V=pi*r*r,其中r为圆的半径。

Input

第一行一个整数N。
第二行为长方形边框一个顶点及其对角顶点的坐标,x1,y,x,y’。
接下去N行,每行两个整数xi,yi,表示盒子内N个点的坐标。
以上所有的整数都在[-1000, 1000]内。

Output

一行,一个整数,长方体盒子剩余的最小空间(结果四舍五入输出)。

Sample Input

2
0 0 10 10
3 3
7 7

Sample Output

50

题解:
额,暴力,然后算出每个点与之前放的圆和墙壁的最小半径,计算答案。
需要注意几点:
(1) 如果这个油滴本身就在另外一个油滴的内部,那么我们就不能选择这个油滴,也就是当两个油滴之间的距离小于那个油滴的半径,我们就要把它变成0!!!

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>using namespace std;int n,x,y,x1,x2,y11,y2;double s=0,ans=0,sum=0,xx,yy,hhh=0;double pi=3.14159;//千万不能设为3.14   血淋淋的教训 struct hh{    int x,y;    double jl;}a[2001];double pc[100];bool b[2001];void dfs(int i,double sum){    double minn=a[i].jl;    b[i]=true;    for(int j=1;j<=n;j++)    {        if(j!=i&&pc[j]!=0)        {            double q=sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));            if(q<=pc[j])            {                minn=0;                break;            }            minn=min(minn,q-pc[j]);        }    }    pc[i]=minn;     sum+=pi*pc[i]*pc[i];    if(ans<sum) ans=sum;    double h=0;    for(int j=1;j<=n;j++)    if(b[j]==false)    {        dfs(j,sum);    }}int main(){    cin>>n;    cin>>x1>>y11>>x2>>y2;    x1+=1000;    x2+=1000;    y11+=1000;    y2+=1000;     x=abs(x1-x2);    y=abs(y11-y2);    s=x*y;    xx=x;    yy=y;    hhh=x*y;    if(n==0)     {        cout<<int(x*y);        return 0;    }    for(int i=1;i<=n;i++)    {        scanf("%d%d",&a[i].x,&a[i].y);        a[i].x+=1000;        a[i].y+=1000;        x=min(abs(x2-a[i].x),abs(x1-a[i].x));        y=min(abs(y2-a[i].y),abs(y11-a[i].y));        if(a[i].x==xx&&a[i].y==yy)        a[i].jl=min(xx,yy);        else a[i].jl=min(x,y);    }    for(int i=1;i<=n;i++)    {        memset(b,false,sizeof(b));        memset(pc,0,sizeof(pc));        dfs(i,0);    }    int u=int (s-ans);    if(u+1<=(s-ans)+0.5)    cout<<u+1;    else cout<<u;    return 0;}

第二题

数列 (Standard IO)
Time Limits: 1000 ms Memory Limits: 65536 KB Detailed Limits

Description

虽然msh长大了,但她还是很喜欢找点游戏自娱自乐。有一天,她在纸上写了一串数字:1,1,2,5,4。接着她擦掉了一个1,结果发现剩下1,2,4都在自己所在的位置上,即1在第1位,2在第2位,4在第4位。她希望擦掉某些数后,剩下的数列中在自己位置上的数尽量多。她发现这个游戏很好玩,于是开始乐此不疲地玩起来……不过她不能确定最多能有多少个数在自己的位置上,所以找到你,请你帮忙计算一下!

Input

第一行为一个数n,表示数列的长度。
接下来一行为n个用空格隔开的正整数,第i行表示数Ai。

Output

一行一个整数,表示擦掉某些数后,最后剩下的数列中最多能有多少个数在自己的位置上,即Ai=i最多能有多少。

Sample Input

5
1 1 2 5 4

Sample Output

3

Data Constraint

Hint

【数据规模】
对于20%的数据,n<=20;
对于60%的数据,n<=100;
对于100%的数据,n<=1000.

题解:
显然dp,我们设f[i][j]为前i个数删除j个数后最多能有多少个数在自己的位置上。
易得到转移方程:f[i][j]=max(max(f[i-1][j]+1,f[i-1][j-1]),f[i][j]);
但是,a[i]恰好为符合当前点的数,那就在前i-1个数删除j个数的情况下加上一
变成了:f[i][j]=max(max(f[i-1][j]+1,f[i-1][j-1]),f[i][j]);

#include<iostream>#include<cstdio>#include<cstring>using namespace std;int n,a[1010],f[1010][1010],ans=0;int main(){    memset(f,0,sizeof(f));    cin>>n;    for(int i=1;i<=n;i++)    {        scanf("%d",&a[i]);    }    for(int i=1;i<=n;i++)    {        for(int j=0;j<=i;j++)        {            if(a[i]==i-j)//当你删除前j个数之后,a[i]恰好为符合当前点的数,那就在前i-1个数删除j个数的情况下加上一             f[i][j]=max(max(f[i-1][j]+1,f[i-1][j-1]),f[i][j]);            else f[i][j]=max(max(f[i-1][j],f[i-1][j-1]),f[i][j]);        }    }    for(int i=0;i<=n;i++)    ans=max(ans,f[n][i]);    cout<<ans;    return 0;}

第三题

软件开发 (Standard IO)
Time Limits: 1000 ms Memory Limits: 65536 KB Detailed Limits

Description

一个软件开发公司同时要开发两个软件,并且要同时交付给用户,现在公司为了尽快完成这一任务,将每个软件划分成m个模块,由公司里的技术人员分工完成,每个技术人员完成同一软件的不同模块的所用的天数是相同的,并且是已知的,但完成不同软件的一个模块的时间是不同的,每个技术人员在同一时刻只能做一个模块,一个模块只能由一个人独立完成而不能由多人协同完成。一个技术人员在整个开发期内完成一个模块以后可以接着做任一软件的任一模块。写一个程序,求出公司最早能在什么时候交付软件。

Input

输入文件第一行包含两个由空格隔开的整数n和m,其中1<=n<=100,1<=m<=100,接下来的n行每行包含两个用空格隔开的整数d1和d2,d1表示该技术人员完成第一个软件中的一个模块所需的天数,d2表示该技术人员完成第二个软件中的一个模块所需的天数,其中1<= d1,d2<=100。

Output

输出文件仅有一行包含一个整数d,表示公司最早能于d天后交付软件。

Sample Input

3 20
1 1
2 4
1 6

Sample Output

18

Data Constraint

Hint

【样例解释】
最快的方案是第一个技术人员完成第二个软件的18个模块,用时18天,第三个技术人员完成第一个软件的18个模块,用时18天,其余的模块由第二个技术人员完成,用时12天,做完所有模块需要18天。如果第一个技术人员完成第二个软件的17个模块,第三个技术人员完成第一个软件的17个模块,其余的模块由第二个技术人员完成,需要用时18天,做完所有模块仍然需要18天,所以少于18天不可能做完所有模块。

题解:
不多说什么,就是dp,但是我们要二分地找时间。
设f[i][j]为前i个人完成了第一个项目的j个模板后还能做的最大的第二个项目的模板数。
方程嘛,就是:f[i][j]=max(f[i-1][j-k]+((mid-(v1[i]*k))/v2[i]),f[i][j]);
ps:v1,v2数组为每个人完成1和2软件同模块的所用的天数,mid为设的时间(天数)。

#include<iostream>#include<cstdio>#include<cstring>using namespace std;int ans=0,v1[101],v2[101],f[101][101],l=1,r=10000;int n,m;int main(){    cin>>n>>m;    for(int i=1;i<=n;i++)    {        scanf("%d%d",&v1[i],&v2[i]);    }    while(l<=r)    {        int mid=(l+r)/2;        memset(f,-0x7f,sizeof(f));        f[0][0]=0;        for(int i=1;i<=n;i++)            for(int j=0;j<=m;j++)                for(int k=0;k<=mid/v1[i];k++)                {                    if(k>j) break;                    f[i][j]=max(f[i-1][j-k]+((mid-(v1[i]*k))/v2[i]),f[i][j]);                }        if(f[n][m]>=m)        {            ans=mid;            r=mid-1;        }        else l=mid+1;    }    cout<<ans;    return 0;}

第四题

黑匣子 (Standard IO)
Time Limits: 1000 ms Memory Limits: 65536 KB Detailed Limits

Description

Black Box是一种原始的数据库。它可以储存一个整数数组,还有一个特别的变量 i 。最开始的时候Black Box是空的,而 i 等于 0。这个 Black Box 要处理一串命令。
命令只有两种:
ADD(x): 把 x 元素放进 Black Box;
GET: i 加 1 ,然后输出 Black box 中第 i 小的数。
记住:第 i 小的数,就是 Black Box里的数的按从小到大的顺序排序后的第 i 个元素。
例如
我们来演示一下一个有11个命令的命令串。
这里写图片描述
现在要求找出对于给定的命令串的最好的处理方法。ADD 和 GET 命令分别最多有200000个。
现在用两个整数数组来表示命令串:
1. A(1), A(2), …, A(M): 一串将要被放进Black Box的元素。每个数都是绝对值不超过2000000000的整数,M <=200000。例如上面的例子就是A=(3, 1, -4, 2, 8, -1000, 2).
2. u(1), u(2), …, u(N): 表示第u(j)个元素被放进了Black Box里后就出现一个GET命令。例如上面的例子中u=(1, 2, 6, 6)。 输入数据不用判错。

Input

第一行,两个整数,M,N,
第二行,M个整数,表示A(1)……A(M),
第三行,N个整数,表示u(1)……u(N)。

Output

输出 Black Box 根据命令串所得出的输出串,一个数字一行。

Sample Input

7 4
3 1 -4 2 8 -1000 2
1 2 6 6

Sample Output

3
3
1
2

Data Constraint

Hint

【数据规模】
对于30%的数据,M<=10000;
对于50%的数据,M<=100000;
对于100%的数据,M<=200000。

题解:
两种方法:权值线段树或大小堆(暴力就是权值线段树脑残版本,只不过权值线段树找位置是log2n的时间,暴力那个枚举是O(n)罢了),但是,毕竟c++选手,果断用优先队列。

#include<iostream>#include<queue>#include<cstring>using namespace std;int n,m,a[200001];priority_queue<int>maxx;priority_queue<int,vector<int>,greater<int> >minn;int main(){    cin>>m>>n;    for(int i=1;i<=m;i++)    {        cin>>a[i];    }    int x;    int j=1;    for(int i=1;i<=n;i++)    {        cin>>x;        while(j<=x)        {            if(!maxx.empty()&&a[j]<maxx.top())            {                minn.push(maxx.top());                maxx.pop();                maxx.push(a[j]);            }            else minn.push(a[j]);            j++;        }        cout<<minn.top()<<endl;        maxx.push(minn.top());        minn.pop();    }    return 0;}
原创粉丝点击