2017.10.10队内互测——高校模拟赛

来源:互联网 发布:淘宝引流宝活动词 编辑:程序博客网 时间:2024/06/06 11:02

2017.10.10队内互测——高校模拟赛

出题人:Dewct,zzk,Cunese,whales

Problem 1 :

题目来源:http://poj.org/problem?id=2709
这里写图片描述
首先确定只对于彩色颜料需要的套装数,再用多余的颜料尝试配置灰色颜料,若无法配置需要的毫升数则再购置一套颜料,为使最大化利用剩余颜料,则由大到小选三种颜料依次-1配置,并在每次配置后排序。

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#define RI register intusing namespace std;int n,maxn,ans,sum,cnt,tot;int num[100010],chi[100010];bool flag;int read(){    char ch=getchar();    int ret=0;    while(ch<'0'||ch>'9')    ch=getchar();    while(ch>='0'&&ch<='9')    {        ret=ret*10+(ch-'0');        ch=getchar();    }    return ret;}bool cmp(int a,int b){    return a>b;}void solve(int k){    tot=0;    for(RI i=1;i<=n;i++)    chi[i]=k*50-num[i];    sort(chi+1,chi+n+1,cmp);    cnt=1;    while(tot<num[n+1])    {        if(chi[cnt+2]==0)        {            k++;            for(int i=1;i<=n;i++)            chi[i]+=50;        }        else        {            tot++;            chi[cnt]--;            chi[cnt+1]--;            chi[cnt+2]--;            sort(chi+1,chi+n+1,cmp);        }    }    ans=k;}int main(){    while(scanf("%d",&n)&&n)    {        maxn=-1e9+7;        for(RI i=1;i<=n+1;i++)        {            num[i]=read();            if(num[i]>maxn&&i<=n)            maxn=num[i];        }        if(maxn%50==0)        ans=maxn/50;        else ans=maxn/50+1;        solve(ans);        printf("%d\n",ans);    }    return 0;}

Problem 2 :

题目来源:http://hzwer.com/4598.html
这里写图片描述
先由每个敌人向各点BFS,求出每个点到最近的敌人的距离,BFS使得每当第一次找的一点时,此时的距离即为到最近敌人的距离。
然后二分移动过程中到敌人的最小距离,BFS检验即可,注意二分写法

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<queue>#define RI register intusing namespace std;int n,x,y,xs,xz,ys,yz,ans1,ans2,a,b,l,r;int dis[1010][1010],dx[]={0,1,-1,0,0},dy[]={0,0,0,1,-1};bool vis[1010][1010];struct point{    int a,b,d;}ls[100010];queue<point>q;void init(){    while(!q.empty())    {        point k=q.front();        q.pop();        for(int i=1;i<=4;i++)        {            int h=k.a+dx[i];int s=k.b+dy[i];            if(h>=x||h<0||s>=y||s<0||dis[h][s]!=-1)            continue;            dis[h][s]=dis[k.a][k.b]+1;            q.push((point){h,s,0});        }    }}int check(int val){    while(!q.empty())    q.pop();    memset(vis,0,sizeof(vis));    if(xs==xz&&ys==yz)    return 0;    vis[xs][ys]=1;    q.push((point){xs,ys,0});    while(!q.empty())    {        point k=q.front();        q.pop();        for(int i=1;i<=4;i++)        {            int h=k.a+dx[i],s=k.b+dy[i];            if(h>=x||h<0||s>=y||s<0||vis[h][s]||dis[h][s]<val)            continue;            vis[h][s]=1;            if(h==xz&&s==yz)            return k.d+1;            q.push((point){h,s,k.d+1});        }    }    return -1;}int main(){    memset(dis,-1,sizeof(dis));    scanf("%d%d%d",&n,&x,&y);    scanf("%d%d%d%d",&xs,&ys,&xz,&yz);    for(int i=1;i<=n;i++)    {        scanf("%d%d",&ls[i].a,&ls[i].b);        dis[ls[i].a][ls[i].b]=0;        q.push((point){ls[i].a,ls[i].b,0});    }    init();    int l=0,r=dis[xs][ys];    while(l<=r)    {        int mid=(l+r)>>1;        int t=check(mid);        if(t==-1)        r=mid-1;        else l=mid+1,ans1=mid,ans2=t;    }    printf("%d %d\n",ans1,ans2);    return 0;}

Problem 3 :

题目来源:http://poj.org/problem?id=1837
这里写图片描述
背包型DP

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>using namespace std;int c,g;int p[110],w[110],dp[31][15010];//30M的空间限制 void solve(){    dp[0][7500]=1;//初始化     for(int i=1;i<=g;i++)    {        for(int j=0;j<=15000;j++)//枚举平衡度         {            if(dp[i-1][j])            for(int k=1;k<=c;k++)            {                dp[i][j+w[i]*p[k]]+=dp[i-1][j];            }        }    }}int main(){    scanf("%d%d",&c,&g);    for(int i=1;i<=c;i++)    scanf("%d",&p[i]);    for(int i=1;i<=g;i++)    scanf("%d",&w[i]);    solve();    printf("%d",dp[g][7500]);//dp[i][j]表示当用了i个钩码平衡度为j时的方案数     return 0;               //7500=25*20*15由数据范围得出,设此平衡度时天平平衡 }
原创粉丝点击