当前位置: 移动技术网 > IT编程>开发语言>C/C++ > 泉五培训Day4

泉五培训Day4

2019年02月01日  | 移动技术网IT编程  | 我要评论

东北牛,吉他谱网站,杨陵租房

t1 收果子

题目

【题目描述】

    有一个果园,有n棵果树依次排成一排,其中已知第 i 棵果树上结了ai个果子。现在要按照果树编号顺序依次收果子,对于一个能装v个果树的果篮,收果子从第1棵果树开始,如果果篮的剩余容积大于等于当前果树所结的果子,那么就可以将此树上的果子全收下来,否则就要拿一个新的篮子来装果子。特别地,如果果篮容积小于某果树的结果数,那么我们认为这样将永远不能收完果子。

    现在假若只能用k个果篮,问按照以上方法能使用不超过k个果篮并收完所有果子的果篮最小容积。

【输入格式】

    输入有两行,第一行两个正整数,代表 n、k,意义如题。

    第二行 n 个正整数ai,代表每棵果树的结果数。

【输出格式】

     输出仅一行,一个正整数,即满足条件的果篮最小容积。

【样例输入】

9 3

1 2 3 4 5 6 7 8 9

【样例输出】

17

【数据规模】

对于 30% 的数据,满足 n, k≦100、ai≦100 。

对于 60% 的数据,满足 n, k≦1000、ai≦105

对于 80% 的数据,满足 n, k≦10000、ai≦105

对于 100% 的数据,满足 n, k≦105 、ai≦109

解析

很显然这是一道二分题,记得加long long 就行了。

code

#include<iostream>
#include<cstring>
#include<cstdio>
#define int long long
using namespace std;
const int n=1e5+5;
const int inf=0x3f3f3f3f;
int n,k;
int a[n],ans;
int minn=inf;
int maxn=-inf;
bool check(int v)
{
    if(maxn>v||minn>v) return 0;
    int cnt=1,water=v;
    for(int i=1;i<=n;i++)
    {
        if(a[i]<=water) water-=a[i];
        else if(a[i]>water)
        {
            cnt++;
            water=v-a[i];
        }
    }
    if(cnt<=k) return 1;
    return 0;
}
signed main()
{
    int l=1,r=0,mid;
    cin>>n>>k;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        maxn=max(maxn,a[i]);minn=min(minn,a[i]);
        r+=a[i];
    }
    while(l<=r)
    {
        mid=(l+r)/2;
        if(check(mid))
        { 
            r=mid-1;
            ans=mid;
        }
        else l=mid+1;
    }
    cout<<ans;
    return 0;
}
view code

 

 

 

 

 

 

t2 食物

题目

【题目描述】

辉夜从月都弄了很多吃的回到了幻想乡,有n种不同的食物,第i种食物的美味度为ti,一份食物的大小为ui,共有vi份。但是麻烦的事情出现了,她要把这些食物运回永远亭,于是辉夜便弄来了m种运载工具。第i种运载工具可以运输大小总和不超过xi的食物,运输一次的费用是yi,总共可以运输zi次。

辉夜打算选取一些食物运回永远亭,他们的美味度之和(每份食物的和,即使他们都是同一种食物)至少是p。值得注意的是,一份食物可以被拆成几份分批次运输,达到永远亭后再组装起来。但是如果不把一份食物完整的运过去,是无法得到美味度的。辉夜想知道最少需要花费的运输费用是多少。由于辉夜的预算仅有50000,因此如果费用超过这个数或者无法获得p的美味度,输出“tat”。

【输入格式】

第一行一个数test,表示有test组数据。

对于每组数据,第一行有三个整数n,m,p。

接下来n行,每行三个整数t,u,v,描述一种食物。

最后m行,每行三个整数x,y,z,描述一种运载工具。

【输出格式】

 对于每组数据,输出辉夜想知道的答案。注意存在无解的情况。

【输入样例】

4

1 1 7

14 2 1

1 2 2

1 1 10

10 10 1

5 7 2

5 3 34

1 4 1

9 4 2

5 3 3

1 3 3

5 3 2

3 4 5

6 7 5

5 3 8

1 1 1

1 2 1

1 1 1

【样例输出】

4

14

12

tat

【数据规模】

test不会很大。

对于前20%的数据,n,m≤20。

对于前50%的数据,n,m≤30,ti,ui,vi,xi,yi,zi≤10。

对于100%的数据,1≤n,m≤200,0≤p≤50000,1≤ti,ui,vii,xi,yi,zi≤100。

解析

我们把问题拆成两部分:

1、选出美味度和不小于p的食物并且空间最小。

2、选出空间之和不小于第一步的结果并且费用尽可能的少。

第一部分只需用背包即可解决。

第二部分我们不妨将状态和答案互换,以费用为状态,以空间为答案,因为答案不超过50000,所以这样是可行的。

code

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int n=210;
const int m=50200;
int n,m,p;
int q,sum,ans;
int t[n],u[n],v[n];
int f[m],w[n*7],v[n*7];
int read()    //快读 
{
    int num=0;char ch=getchar();
    while(ch<'0' || ch>'9') ch=getchar();
    while(ch>='0' && ch<='9') num=(num<<1)+(num<<3)+ch-'0',ch=getchar();
    return num;
}
int main()
{
    int t=read();
    while(t--)
    {
    //求出最小空间
        sum=0;
        memset(v,0,sizeof(v));
        memset(w,0,sizeof(w));
        memset(f,0,sizeof(f));
        n=read();m=read();p=read();
        for(register int i=1;i<=n;i++)
        {
            t[i]=read();u[i]=read();v[i]=read();
            int j;
            for(j=1;j<=v[i];j<<=1)
            {
                v[++sum]=t[i]*j;
                w[sum]=u[i]*j;
                v[i]-=j;
            }
            if(v[i])
            {
                v[++sum]=t[i]*v[i];
                w[sum]=u[i]*v[i];
            }
        }
        for(register int i=1;i<=sum;i++)
            for(register int j=m-1;j>=w[i];j--) f[j]=max(f[j],f[j-w[i]]+v[i]);
        q=-1;
        for(register int i=1;i<m;i++) if(f[i]>=p){q=i;break;}//求出满足美味度不小于p的最小价值
        if(q<0)//不成立的情况
        {
            cout<<"tat"<<endl;
            for(register int i=1;i<=m;i++) q=read(),q=read(),q=read();
            continue;
        }
        //求出尽可能小的费用
        memset(v,0,sizeof(v));
        memset(w,0,sizeof(w));
        memset(f,0,sizeof(f));
        sum=0;
        for(register int i=1;i<=m;i++)
        {
            t[i]=read();u[i]=read();v[i]=read();
            int j;
            //二进制拆分
            for(register int j=1;j<=v[i];j<<=1)
            {
                v[++sum]=t[i]*j;
                w[sum]=u[i]*j;
                v[i]-=j;
            }
            if(v[i])
            {
                v[++sum]=t[i]*v[i];
                w[sum]=v[i]*u[i];
            }
        }
        for(register int i=1;i<=sum;i++)
            for(register int j=50000;j>=w[i];j--) f[j]=max(f[j],f[j-w[i]]+v[i]);
        ans=-1;
        for(register int i=1;i<=50000;i++) if(f[i]>=q){ans=i;break;}//求出最小花费
        if(ans<0){cout<<"tat"<<endl;continue;} 
        cout<<ans<<endl;
    }
    return 0;
}
view code

 

 

 

 

 

 

t3 到天堂的路

题目

【题目描述】

到天堂的道路是一个笛卡尔坐标系上一个nxm的长方形通道(顶点在(0,0)和(n,m)),小w从最左边任意一点进入,从右边任意一点走到天堂。

最左最右的距离为n,上下边界距离为m。

其中长方形内有k个star,每个star都有一个整点坐标,star的大小可以忽略不计。

每个star以及长方形上下两个边缘(宇宙的边界)都有引力,所以为了成功到达heaven小w离他们越远越好。

请问小w走到终点的路径上,距离所有星星以及边界的最小距离最大值可以为多少?

【输入格式】

 一行三个整数n,m,k。

接下来k行,每行两个整数xi,yi,表示一个点的坐标。

【输出格式】

 一行一个整数表示答案,绝对误差不能超过10-6

【输入样例】

10 5 2

1 1

2 3

【输出样例】

1.11803399

【数据规模】

对于20%的数据,k≤10。

对于50%的数据,k≤400。

对于80%的数据,k≤1000。

对于100%的数据,k≤6000,n,m≤106

解析

最小距离的最大值,考虑从将几个点,从下界连到上界,这条路径中的最长边的一半,即我们想要的答案。

一条路径的最长边,即最大值。

所有路径中的最长边的最小值,即最小距离。

所以求出最长边的最小值即可。

我们要找到所有路径中的所有最长边(相对于该条路径而言),然后在这些最长边中找到一个最小值,最小值除以二即为答案。

code

#include<iostream>
#include<cstdio>
#include<cmath>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int n=6000+5;
int water[n];
int n,m,k,x[n],y[n];
double dis[n],ans;
double calc(int x,int y,int l,int r)
{
    return sqrt((double)(x-l)*(x-l)+(double)(y-r)*(y-r));
}
int main()
{
    cin>>n>>m>>k;
    for(int i=1;i<=k;i++) cin>>x[i]>>y[i];
    for(int i=1;i<=k;i++) dis[i]=m-y[i];
    dis[k+1]=m;
    dis[0]=2e9;
    while(1)
    {
        int mi=0;
        for(int i=1;i<=k+1;i++)
            if(!water[i] && dis[i]<dis[mi]) mi=i;
        ans=max(ans,dis[mi]);
        if(mi==k+1)
        {
            cout<<ans/2;
            return 0;
        }
        for(int i=1;i<=k;i++) dis[i]=min(dis[i],calc(x[i],y[i],x[mi],y[mi]));
        dis[k+1]=min(dis[k+1],y[mi]);
        water[mi]=1;
    }
    return 0;
}
view code

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网