【队内胡策】2017.11.3

16 篇文章 0 订阅
9 篇文章 0 订阅

T1

第二题
【题目描述】
给你两个日期,问这两个日期差了多少毫秒。
【输入格式】
两行,每行一个日期,日期格式保证为“YYYY-MM-DD hh:mm:ss”这种形
式。第二个日期时间一定比第一个日期时间要大两个日期的年份一定都是 21 世
纪的年份。
【输出格式】
一行一个整数代表毫秒数。
【样例输入 1】
2000-01-01 00:00:00
2000-01-01 00:00:01
【样例输出 1】
1000
【样例输入 2】
2000-01-01 00:00:00
2000-11-11 00:00:00
【样例输出 2】
27216000000
【样例解释】
从前有座山。
【数据范围与规定】
对于10%的数据, 两个日期相同。
对于20%的数据,两个日期只有秒数可能不同。
对于30%的数据,两个日期只有秒数、分钟数可能不同。
对于40%的数据,两个日期的年月日一定相同。
对于60%的数据,两个日期的年月一定相同。
对于80%的数据,两个日期的年份一定相同。
对于100%的数据,两个日期一定都是 21 世纪的某一天,且第二个日期一定
大于等于第一个日期。

真麻烦

小学知识回顾:“一般的,能被4整除的年份是闰年,不能被4整除的年份是平年.如:1988年2008年是闰年;2005年2006年2007年是平年.但是如果是世纪年(也就是整百年),就只有能被400整除才是闰年,否则就是平年.如:2000年就是闰年,1900年就是平年
闰年的2月有29天,平年的2月只有28天. ”
然而我都按照能否整除400来判了。只卡掉两组。
数据不卡400的,懒得修正了233.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char c;
unsigned long long a[10],b[10];
int x[]={30,31,30,31,30,31,30,31,31,30,31,30,31};
int xa[]={30,31,30,31,30,31,30,31,31,30,31,30,31},xb[]={30,31,30,31,30,31,30,31,31,30,31,30,31};
int t[60],sum,summ,ta[60],tb[60];
int nian[10000+1],fn[10000+1];//nian:每年的天数 fn:前x年的天数 
int main()
{
    //freopen("two.in","r",stdin);
    //freopen("two.out","w",stdout);
    cin>>a[1]>>c>>a[2]>>c>>a[3]>>a[4]>>c>>a[5]>>c>>a[6];
    cin>>b[1]>>c>>b[2]>>c>>b[3]>>b[4]>>c>>b[5]>>c>>b[6];
    if(a[1]==b[1]&&a[2]==b[2]&&a[3]==b[3]&&a[4]==b[4]&&a[5]==b[5]&&a[6]==b[6]) puts("0");//两个日期相同
    else if(a[1]==b[1]&&a[2]==b[2]&&a[3]==b[3]&&a[4]==b[4]&&a[5]==b[5]&&a[6]!=b[6]) cout<<(b[6]-a[6])*1000<<'\n';//只有秒数不同
    else if(a[1]==b[1]&&a[2]==b[2]&&a[3]==b[3]&&a[4]==b[4]) cout<<(b[5]*60+b[6]-a[5]*60-a[6])*1000<<'\n';//秒数、分钟数不同 
    else if(a[1]==b[1]&&a[2]==b[2]&&a[3]==b[3]) cout<<(b[4]*3600+b[5]*60+b[6]-a[4]*3600-a[5]*60-a[6])*1000<<'\n';//年月日相同
    else if(a[1]==b[1]&&a[2]==b[2]) cout<<(b[3]*86400+b[4]*3600+b[5]*60+b[6]-a[3]*86400-a[4]*3600-a[5]*60-a[6])*1000<<'\n';//年月相同
    else if(a[1]==b[1])//年份相同,从月份开始不同
    {
        if(a[1]%4==0) x[2]=29;//闰年
        else x[2]=28;//平年
        t[0]=0;
        for(int i=1;i<=12;i++)
        {
            sum+=x[i];
            t[i]=sum;//前i个月有多少天 
        }
        cout<<(t[b[2]-1]+b[3]-t[a[2]-1]-a[3])*86400+b[4]*3600+b[5]*60+b[6]-a[4]*3600-a[5]*60-a[6]<<"000"<<'\n';
    }
    else
    {
        for(int i=2000;i<=3000;i++)
        {
            if(i%4==0) nian[i]=366;//闰年
            else nian[i]=365;//第i年有多少天 
        }
        summ=0;
        for(int i=2000;i<=3000;i++)
        {
            summ+=nian[i];
            fn[i]=summ;//前i年有多少天 
        }
        unsigned long long ts;
        if(a[1]%4==0) xa[2]=29;//闰年
        else xa[2]=28;//平年
        if(b[1]%4==0) xb[2]=29;
        else xb[2]=28;
        ta[0]=0,sum=0;
        for(int i=1;i<=12;i++)
        {
            sum+=xa[i];
            ta[i]=sum;//前i个月有多少天 
        }
        tb[0]=0,sum=0;
        for(int i=1;i<=12;i++)
        {
            sum+=xb[i];
            tb[i]=sum;//前i个月有多少天 
        }
        ts=fn[b[1]-1]+tb[b[2]-1]+b[3]-fn[a[1]-1]-ta[a[2]-1]-a[3];
        cout<<ts*86400+b[4]*3600+b[5]*60+b[6]-a[4]*3600-a[5]*60-a[6]<<"000"<<'\n';
    }
    //fclose(stdin);
    //fclose(stdout);
    return 0;
} 

T2

死亡
【问题描述】
现在有M个位置可以打 sif,有N + 1个人在排队等着打 sif。 现在告诉你前N
个人每个人需要多长的时间打 sif,问你第N + 1个人什么时候才能打 sif。(前N
个人必须按照顺序来)
【输入格式】
第一行两个整数N,M如上所述。
接下来N行每行一个整数代表每个人所需要用的时间。
【输出格式】
一行一个整数表示答案。
【样例输入】
3 2
1 1 1
【样例输出】
1
【样例解释】
山里有座庙。
【数据规模与约定】
N M
1 10 10
2 20 10
3 50 10
4 1000 500
5 2000 500
6 5000 500
7 100000 5000
8 100000 10000
9 100000 20000
10 100000 50000
对于100%的数据,每个人所需用的时间不超过10^5。
用小根堆维护一个贪心。模拟一个位置空了,下一个人马上接上的过程,最后输出那个最短的时间,就是第n+1个人接上的时间。
这个题跟接水问题不太一样。。接水问题是输出所有人全部完成接水的时间,即小根堆的堆底。

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int maxn=500000+5;
int a[maxn],t[maxn];
int n,m;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    priority_queue<int,vector<int>,greater<int> >q;
    for(int i=1;i<=m;i++) q.push(0);
    for(int i=1;i<=n;i++)
    {
        int k=m;
        int f=q.top();
        q.pop();
        q.push(f+a[i]);
    }
    cout<<q.top()<<'\n';
    return 0;
}

听说要开longlong。
嗯好像确实要开longlong。
以后要注意考虑一下最差的情况,然后确定是否要开longlong。

T3

凝视
【问题描述】
背包是个好东西,希望我也有。
给你一个二维的背包,它的体积是N × M。现在你有一些大小为1 × 2和1 ×
3的物品,每个物品有自己的价值。你希望往背包里面装一些物品,使得它们的
价值和最大,问最大的价值和是多少。
【输入格式】
第一行一个整数T代表该测试点的数据组数。
对于每组数据,第一行有四个整数N, M, n1, n2,其中n1, n2分别代表大小为
1 × 2和大小为1 × 3的物品个数。
接下来一行有n1个数代表每个1 × 2物品的价值。
接下来一行有n2个数代表每个1 × 3物品的价值。
【输出格式】
对于每组询问,输出能够达到的价值最大值。
【样例输入】
1
2 3 2 2
1 2
1 2
【样例输出】
4
【样例解释】
庙里有座山。
【数据规模与约定】
对于20%的数据, N, M ≤ 10, n1, n2 ≤ 100。
对于70%的数据, N, M ≤ 100,n1, n2 ≤ 2000。
对于100%的数据, 1 ≤ T ≤ 10,1 ≤ N, M ≤ 500,0 ≤n1, n2 ≤ 10000。
贪心可做
背包是二维,相当于一个方块
有1*2和1*3的两种物(fang)品(kuai),每种物品有各自的价值,选择其中一些放到n*m的方块上,使总价值最大
不管怎么放,把输入的两种不同面积小方块的价值分别从大到小排序
如果这个面积的可以放,那么优先放价值最大的(贪心思想)
排序后分别处理出前缀和
确定上限 暂时认为如果只放1*3的方块,那么大方块上最多能放(n*m)/3个1*3的方块
如果只放1*2的方块,则最多可以放(n*m)/2个
由于1*3的方块比较容易遇到剩余空间足够但是放不下的情况,所以先确定能放多少1*3的方块,
再使总面积与之作差,计算出可以放多少1*2的方块
对于1*3的方块,如果n或m==2并且n或m%2==2,那么会剩余4个格子,四个格子构成一个正方形,只能用1*2的方块填上,这时候能放的1*3的最大值就成了(n*m-4)/3
同时要先预处理出大方块为2*2的情况
对于上限,最终放入的1*2或1*3的方块数量不能大于拥有的两种方块的方块数量

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100000+10;
int a2[maxn],a3[maxn];
int t,n,m,x,y;
bool cmp(int x,int y)
{
    return x>y;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        int maxx=0,ans=0;
        scanf("%d%d%d%d",&n,&m,&x,&y);
        for(int i=1;i<=x;i++) scanf("%d",&a2[i]);
        for(int i=1;i<=y;i++) scanf("%d",&a3[i]);
        sort(a2+1,a2+x+1,cmp);
        sort(a3+1,a3+y+1,cmp);
        for(int i=1;i<=x;i++) a2[i]+=a2[i-1];
        for(int i=1;i<=y;i++) a3[i]+=a3[i-1];
        if((n%3==2)&&(m%3==2)&&(n==2||m==2)) maxx=(n*m-4)/3;
        else maxx=min((n*m)/3,y);
        if(n==2&&m==2) ans=a2[2];
        else for(int i=0;i<=maxx;i++)
        {
            int re=n*m-i*3; 
            ans=max(ans,a3[i]+a2[min(re/2,x)]);
        }
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值