2019中山纪念中学夏令营-Day1[JZOJ]

T1 题目描述:

题目描述

         Wexley最近发现了一个古老的屏幕游戏。游戏的屏幕被划分成n列。在屏幕的底端,有一个宽为m列的篮子(m<n)。在游戏过程中,Wexley能左右移动这个篮子,            Wexley的操作很犀利,移动是瞬间完成的,但是篮子必须始终都在屏幕中。 苹果从屏幕的顶端落下,每个苹果从n列中的某一列顶端掉落,垂直掉落到屏幕的底端。每个苹果总是在上一个苹果掉落到底端的时候开始掉落。Wexley想要通过移动篮子来接住所有的苹果。起先,篮子在屏幕的最左端。
         求出Wexley要接住所有的苹果所需移动的最短距离。 
 

输入

第一行,两个整数n、m,如题所述
第二行,一个整数k,表示掉落的苹果总数
接下来k行,每行一个整数Ai,表示每个苹果掉落的位置

输出

一行一个整数,表示所需移动最短距离
 

样例输入

Sample Input1:
5 1
3
1
5
3

Sample Input2:
5 2
3
1
5
3

 

样例输出

Sample Output1:
6

Sample Output2:
4

 
 

数据范围限制

【数据范围】
对于30%的数据,m<n<=5,k<=10
对于100%的数据,1<=m<n<=10,1<=k<=20

思路:贪心模拟,使每次移动数尽量少即可.难度较容易。

附上AC代码:(考试完了重新码的,考试的时候的代码有点小问题)

#include <cstdio>
#include <iostream>
using namespace std;
int n,m,k,a[21];
int b[21],head,ans,tmp;
int main()
{
    freopen("apple.in","r",stdin);
    freopen("apple.out","w",stdout);
    scanf("%d %d",&n,&m);
    scanf("%d",&k);
    b[0]=1;
    for(int i=1;i<=k;i++)
    {
        scanf("%d",&a[i]);
    }
    head=m;
    for(int i=1;i<=k;i++)
    {
        if(head>=a[i] && (head-m+1)<=a[i])
        continue;
        if(head<a[i])
        {
            ans+=a[i]-head;
            head+=a[i]-head;
            continue;
        }
        if((head-m+1)>a[i])
        {
            int tmp=head;
            head=a[i]+m-1;
            ans+=tmp-head;
            continue;
        }
    }
    printf("%d",ans);
}

T2 

题目描述

         Leo是一个快乐的火星人,总是能和地球上的OIers玩得很high。
         2012到了,Leo又被召回火星了,在火星上没人陪他玩了,但是他有好多好多积木,于是他开始搭积木玩。
       火星人能制造n种积木,积木能无限供应。每种积木都是长方体,第i种积木的长、宽、高分别为li、wi、hi。积木可以旋转,使得长宽高任意变换。Leo想要用这些积木搭一个最高的塔。问题是,如果要把一个积木放在另一个积木上面,必须保证上面积木的长和宽都严格小于下面积木的长和宽。这意味着,即使两块长宽相同的积木也不能堆起来。
       火星上没有电脑,好心的你决定帮助Leo求出最高的塔的高度。

【提示】
每种积木都可以拆分成高度分别为li、wi、hi的三种积木,另两边作为长和宽,保证长>=宽。
 

输入

第一行,一个整数n,表示积木的种数
接下来n行,每行3个整数li,wi,hi,表示积木的长宽高

输出

一行一个整数,表示塔高的最大值
 

样例输入

Sample Input1:
1
10 20 30


Sample Input2:
2
6 8 10
5 5 5



Sample Input3:
5
31 41 59
26 53 58
97 93 23
84 62 64
33 83 27

 

样例输出

Sample Output1:
40


Sample Output2:
21


Sample Output3:
342
 

数据范围限制

对于30%的数据 n<=8
对于100%的数据 n<=3000,最后答案不会超过32位整型

思路:标答:动态规划。

  骗分:暴力DFS.

附上DFS30分代码TLE

#include <cstdio>
#include <iostream>
using namespace std;
int n,a[3002][3],ans=0,mina;
const int inf=999999999;
void swap(int a,int b)
{
    int c=b;
    b=a;
    a=c;
}
void dfs(int l,int w,int high)
{
    if(high>ans)
    ans=high;
    if(w==mina)
    {
        return;
    }
    for(int i=1;i<=n;i++)
    {
        if(a[i][0]<l && a[i][1]<w)
        dfs(a[i][0],a[i][1],high+a[i][2]);
        if(a[i][0]<w && a[i][1]<l)
        dfs(a[i][1],a[i][0],high+a[i][2]);
        if(a[i][0]<l && a[i][2]<w)
        dfs(a[i][0],a[i][2],high+a[i][1]);
        if(a[i][0]<w && a[i][2]<l)
        dfs(a[i][2],a[i][0],high+a[i][1]);
        if(a[i][1]<l && a[i][2]<w)
        dfs(a[i][1],a[i][2],high+a[i][0]);
        if(a[i][1]<w && a[i][2]<l)
        dfs(a[i][2],a[i][1],high+a[i][0]);
        if(a[i][1]>l && a[i][2]>w)
        continue;
    }
}
int main(){
    freopen("brick.in","r",stdin);
    freopen("brick.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        int a1,b1,c1;
        scanf("%d %d %d",&a1,&b1,&c1);
        if(c1>b1)
        swap(c1,b1);
        if(a1<b1)
        swap(a1,b1);
        if(c1>b1)
        swap(c1,b1);
        if(mina>c1)
        mina=c1;
        a[i][0]=a1;a[i][1]=b1;a[i][2]=c1;
    }
    dfs(inf,inf,0);
    printf("%d",ans);
}

100分代码:

#include <cstdio>
#include <algorithm>
#include <cstring>
struct Node{
    int w,l,h;
}a[10001];
int Max(int a,int b)
{
    if(a>b)
    return a;
    return b;
}
int Min(int a,int b)
{
    if(a>b)
    return b;
    return a;
}
bool bdx(Node c,Node d)
{
    return c.l<d.l;
}
int main()
{
    freopen("brick.in","r",stdin);
    freopen("brick.out","w",stdout);
    int n,f[10001],ans;
    scanf("%d",&n);
    int o,p,q;
    for(int i=1;i<=n;i++)
    {
        scanf("%d %d %d",&o,&p,&q);
        a[i].l=Max(o,p);a[i].w=Min(o,p);a[i].h=q;
        a[i+n].l=Max(o,q);a[i+n].w=Min(o,q);a[i+n].h=p;
        a[i+2*n].l=Max(p,q);a[i+2*n].w=Min(p,q);a[i+2*n].h=o;
    }
    std::sort(a+1,a+3*n+1,bdx);
    for(int i=1;i<=3*n;i++)
        f[i]=a[i].h;
    for(register int i=3*n;i>=1;i--)
        for(register int j=i+1;j<=3*n;j++)
            if(a[i].w<a[j].w && a[i].l != a[j].l)
                f[i]=Max(f[j]+a[i].h,f[i]);
    for(int i=1;i<=3*n;i++)
    ans=Max(ans,f[i]);
    printf("%d",ans);
}

T4

题目描述

           马上假期就要到了,THU的神犇Leopard假期里都不忘学霸,现在有好多门功课,每门功课都耗费他1单位时间来学习。
           他的假期从0时刻开始,有1000000000个单位时间(囧rz)。在任意时刻,他都可以任意一门功课(编号1~n)来学习。
           因为他在每个单位时间只能学习一门功课,而每门功课又都有一个截止日期,所以他很难完成所有n门功课。
           对于第i门功课,有一个截止时间Di,若他能学完这门功课,他能够获得知识Pi。
           在给定的功课和截止时间下,Leopard能够获得的知识最多为多少呢?
 

输入

第一行,一个整数n,表示功课的数目
接下来n行,每行两个整数,Di和Pi

输出

输出一行一个整数,表示最多学得的知识数
 

样例输入

3
2 10
1 5
1 7


 

样例输出

17

【样例说明】
第一个单位时间学习第3个功课(1,7),然后在第二个单位时间学习第1个功课(2,10)
 

数据范围限制

10% n<=25
60% n<10000
100% 1<=n<=100000,Di、Pi<=1000000000
最后的答案可能超过32位整型
 

思路:标答:最小堆

  接近标答:贪心。

附上80分贪心代码(TLE+RE)

#include <cstdio>
#include <algorithm>
#define rr register
bool time[100001],bj;
struct Node{
    int di,pi;
}a[100001];
inline bool bdx(Node c,Node d)
{
    return c.pi>d.pi;
}
int main()
{
    freopen("study.in","r",stdin);
    freopen("study.out","w",stdout);
    rr long long ans=0LL;
    rr int n,mark=0;
    scanf("%d",&n);
    for(rr int i=1;i<=n;i++)
    scanf("%d %d",&a[i].di,&a[i].pi);
    std::sort(a+1,a+n+1,bdx);
    for(rr int i=1;i<=n;i++)
    {
        if(!time[a[i].di])
        {
            time[a[i].di]=true;
            ans+=a[i].pi;
        }
        else
        {
            rr int j=a[i].di;
            while(time[j])
            j--;
            if(j<1)
            continue;
            ans+=a[i].pi;
            time[j]=true;
        }
    }
    printf("%lld",ans);
}

目前这道题还没AC...

原文地址:https://www.cnblogs.com/XYYXP/p/2019-8-1_ZSJNZX_OJ_TEAM-C_PUJI_DAY1.html