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

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 int
using 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 int
using 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由数据范围得出,设此平衡度时天平平衡 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值