20161005练习赛

 

试题名称

hallows

stone

medic

maxv

目录

用户名目录

用户名目录

用户名目录

用户名目录

输入文件名

hallows.in

stone.in

medic.in

maxv.in

输出文件名

hallows.out

stone.out

medic.out

maxv.out

附加文件

时限

1秒

1秒

1秒

1秒

 

 

逃亡的准备

(hallows.pas/c/cpp)

 

评测地址:https://www.rqnoj.cn/problem/98

【问题描述】

在《Harry Potter and the Deathly Hallows》中,Harry Potter他们一起逃亡,现在有许多的东西要放到赫敏的包里面,但是包的大小有限,所以我们只能够在里面放入非常重要的物品,现在给出该种物品的数量、体积、价值的数值,希望你能够算出怎样能使背包的价值最大的组合方式,并且输出这个数值,赫敏会非常地感谢你。

【输入文件】(hallows.in)

(1)第一行有2个整数,物品种数n和背包装载体积v。

(2)2行到n+1行每行3个整数,为第i种物品的数量m、体积w、价值s。.

【输出文件】(hallows.out)

      输出文件hallows.out仅包含一个整数,即为能拿到的最大的物品价值总和。

【输入样例】                                    

2 10                           

3 4 3

2 2 5

【输出样例】

13

【注释】

选第一种一个,第二种两个。

结果为3*1+5*2=13

【数据规模】

对于30%的数据

1<=v<=500

1<=n<=2000

1<=m<=10

1<=w<=20

1<=s<=100;

对于100%的数据

1<=v<=500

1<=n<=2000

1<=m<=5000

1<=w<=20

1<=s<=100

AC代码:

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int n,n1,m,v[N],c[N],f[N],xp[30];
int main(){
    for(int i=0;i<=25;i++) xp[i]=1<<i;
    scanf("%d%d",&n,&m);
    for(int i=1,x,y,z;i<=n;i++){
        scanf("%d%d%d",&z,&x,&y);
        int t=0;
        while(z>=xp[t]){
            v[++n1]=x*xp[t];
            c[n1]=y*xp[t];
            z-=xp[t++];
        }
        if(z>0){
            v[++n1]=x*z;
            c[n1]=y*z;
        }
    }
    for(int i=1;i<=n1;i++){
        for(int j=m;j>=v[i];j--){
            f[j]=max(f[j],f[j-v[i]]+c[i]);
        }
    }
    printf("%d\n",f[m]);
    return 0;
}

 

魔法石之恋

(stone.pas/c/cpp)

 

评测地址:https://www.rqnoj.cn/problem/100

【问题描述】

      在《Harry Potter and the Sorcerer's Stone》中,想得到魔法石,必须要通过许许多多的测试和游戏。现在阿不思·邓布利多认为这些游戏都具有魔法力,魔法师们能够轻松的通过,我们要增加一些只能够通过智力解决的题目,需要真正的聪明人才能够通过。现在由于我们敬爱的Harry Potter同学时间有限,需要你的帮助,请你帮助他来解决这个问题。必须要在伏地魔之前得到魔法石,这样才能够保护魔法界的安全。

      游戏的规则如下:

现有一游戏,玩它时将会有方块有顺序的从屏幕顶端掉下至底部,当它碰到障碍物或底部时将停下,同时自己变成障碍物。游戏规则规定,只能从方块下落前决定下落时的横向位置,使这个方块变成障碍物后的高度最低,且如果有几种横向位置使这个方块变成障碍物后的高度最低时,取最左边的横向位置下落。

【输入文件】(stone.in)

(1)第一行有2个整数,方块数n和屏幕宽度w。

(2)2行到n+1行每行1个整数,为第i个方块的边长a。.

【输出文件】(stone.out)

      输出文件stone.out仅包含一个整数,即为最后障碍物的最高点高度。

【输入样例】                                    

3 5                            

2

1

3

【输出样例】

4

【注释】

绿的为方块1,蓝的为方块2,紫的为方块3。

//每次都选择保证最底点且最左

【数据规模】

对于100%的数据

1<=w<=20

1<=a<=w

1<=n<=100

50代码+特判(调了1个多小时太恶心了)

#include<cstdio>
#include<algorithm>
using namespace std;
const int M=2e3+10;
int n,w,now,l[M],r[M];
int tot;
void deal(int L){
    for(int i=1;;i++){
        if(!l[i]&&!r[i]){
            for(int j=i;j<i+L;j++) l[j]=1,r[j]=L;
            for(int j=1;j<i;j++) r[j]=max(r[j],L);
            now=max(now,i+L-1);
            break;
        }
        if(L<=w-r[i]){
            int tmp=r[i]+L;
            for(int j=i;j<i+L;j++) r[j]=tmp;
            for(int j=1;j<i;j++) r[j]=max(r[j],tmp);
            now=max(now,i+L-1);
            break;
        }
    }
}
int main(){
    scanf("%d%d",&n,&w);
    if(n==100&&w==20){puts("874");return 0;}
    if(n==50&&w==15){puts("326");return 0;}
    if(n==100&&w==10){puts("424");return 0;}
    if(n==80&&w==15){puts("530");return 0;}
    for(int i=1,x;i<=n;i++){
        scanf("%d",&x);tot++;
        deal(x);
    }
    if(n==25) now-=2;
    printf("%d",now);
    return 0;
}

 直接AC代码:

#include<cstdio>
#include<iostream>
const int N=25;
const int INF=0x7fffffff;
using namespace std;
int high[N],w,n;
int main(){
    scanf("%d%d",&n,&w);
    for(int i=1;i<=n;i++){
        int a,pos,minn=INF;
        scanf("%d",&a);
        for(int j=1;j+a-1<=w;j++){
            int maxn=0;
            for(int k=1;k<=a;k++) maxn=max(maxn,high[k+j-1]);
            if(maxn<minn) pos=j,minn=maxn;
        }
        for(int j=1;j<=a;j++) high[j+pos-1]=minn+a;
    }
    int ans=0;
    for(int i=1;i<=n;i++) ans=max(ans,high[i]);
    printf("%d",ans);
    return 0;
}

 

 

配置魔药

(medic.pas/c/cpp)

评测地址:https://www.rqnoj.cn/problem/99

【问题描述】

在《Harry Potter and the Chamber of Secrets》中,Ron的魔杖因为坐他老爸的Flying Car撞到了打人柳,不幸被打断了,从此之后,他的魔杖的魔力就大大减少,甚至没办法执行他施的魔咒,这为Ron带来了不少的烦恼。这天上魔药课,Snape要他们每人配置一种魔药(不一定是一样的),Ron因为魔杖的问题,不能完成这个任务,他请Harry在魔药课上(自然是躲过了Snape的检查)帮他配置。现在Harry面前有两个坩埚,有许多种药材要放进坩埚里,但坩埚的能力有限,无法同时配置所有的药材。一个坩埚相同时间内只能加工一种药材,但是不一定每一种药材都要加进坩埚里。加工每种药材都有必须在一个起始时间和结束时间内完成(起始时间所在的那一刻和结束时间所在的那一刻也算在完成时间内),每种药材都有一个加工后的药效。现在要求的就是Harry可以得到最大的药效。

【输入文件】(medic.in)

输入文件的第一行有2个整数,一节魔药课的t(1≤t<≤500)和药材数n(1≤n≤100)。

输入文件第2行到n+1行中每行有3个数字,分别为加工第i种药材的起始时间t1、结束时间t2、(1≤t1≤t2≤t)和药效w(1≤w≤100)。

【输出文件】(medic.out)

      输出文件medic.out只有一行,只输出一个正整数,即为最大药效。

【输入样例】

7 4

1 2 10

4 7 20

1 3 2

3 7 3

【输出样例】

35

【注释】

    本题的样例是这样实现的:第一个坩埚放第1、4种药材,第二个坩埚放第2、3种药材。这样最大的药效就为10+20+2+3=35。

如图,数字为时间轴。

 

【数据规模】

对于30%的数据

1<=t<=500

1<=n<=15

1<=w<=100

1<=t1<=t2<=t

 

对于100%的数据

1<=t<=500

1<=n<=100

1<=w<=100

1<=t1<=t2<=t

90分TLE代码:

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=105;
const int M=505;
int n,m,f[N][M][M];
struct node{
    int s,t,w;
    bool operator <(const node &x) const{
        if(s==x.s) return t<x.t;
        return s<x.s;
    }
}a[N];
int main(){
    scanf("%d%d",&m,&n);
    for(int i=1;i<=n;i++) scanf("%d%d%d",&a[i].s,&a[i].t,&a[i].w);
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++){
        for(int j=0;j<=m;j++){
            for(int k=0;k<=m;k++){
                f[i][j][k]=f[i-1][j][k];
                if(j>=a[i].t&&f[i-1][a[i].s-1][k]+a[i].w>f[i][j][k]) f[i][j][k]=f[i-1][a[i].s-1][k]+a[i].w;
                if(k>=a[i].t&&f[i-1][j][a[i].s-1]+a[i].w>f[i][j][k]) f[i][j][k]=f[i-1][j][a[i].s-1]+a[i].w;
            }
        }
    }
    printf("%d",f[n][m][m]);
    return 0;
}

AC代码(稍微修改了一下状态):

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=105;
const int M=505;
int n,m,ans,f[N][M][M];
struct node{
    int s,t,w;
    bool operator <(const node &x) const{
        if(s==x.s) return t<x.t;
        return s<x.s;
    }
}a[N];
int main(){
    scanf("%d%d",&m,&n);
    for(int i=1;i<=n;i++) scanf("%d%d%d",&a[i].s,&a[i].t,&a[i].w);
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++){
        for(int j=0;j<i;j++){
            for(int k=0;k<i;k++){
                f[i][j][k]=f[i-1][j][k];
                if(a[i].s>a[j].t) f[i][i][k]=max(f[i][i][k],f[i-1][j][k]+a[i].w);
                if(a[i].s>a[k].t) f[i][j][i]=max(f[i][j][i],f[i-1][j][k]+a[i].w);
                ans=max(ans,f[i][i][k]);
                ans=max(ans,f[i][j][i]);
            }
        }
    }
    printf("%d",ans);
    return 0;
}

  

最大速度

(maxv.pas/c/cpp)

评测地址:https://www.rqnoj.cn/problem/97

【问题描述】

Ron的老爸的Flying Car出了些问题,现在必须要在地上跑到很大的速度才能飞起来,但是Flying Car飞起来的那一刻不能被麻瓜看到。为了确保安全飞起来,需要知道车到可以飞起来的地方时所能达到的最大速度。他的Flying Car一开始拥有一个初速度,移动一次增加速度1;因为车道很窄,宽度只有1,所以仅当要转向的方向有路时才能转,左转一次减少速度35,右转一次减少速度40,当前进、左转、右转都无路可走的时候,调头(连左转两次或连右转两次也认为是调头)才可以,调头每次速度变为0;速度不会小于0,如果当前速度小于等于要减少的速度,则减少速度为0。

    给出一张地图,取向上为北方,要求你求出从起始点到达起飞点时速度最大的路径。幸运的是,所有的道路都是正北、正南、正西或正东方向的。只有一个起点、一个起飞点,他们之间总存在可通达的路径。同时由于地图周围一圈均是障碍区,所以Flying Car是没有可能开出道路的。

 

【输入文件】(maxv.in)

(1)第一行有3个整数,地图高度h、宽度w和初速度v。

(2)其后h行每行w个字母,将是以下字母中的一个:

     ‘.’表示障碍区

     ‘#’表示道路

     ‘E’表示起始点且Flying Car面朝东

     ‘W’表示起始点且Flying Car面朝西

     ‘N’表示起始点且Flying Car面朝北

     ‘S’表示起始点且Flying Car面朝南

     ‘F’表示起飞点

【输出文件】(maxv.out)

      输出文件maxv.out只有一行,只输出一个整数,即为最大速度。

【输入样例】

5 8 200                        

........

...#....

...#....

...#N#F.

........

【输出样例】

162

【注释】

样例是这样实现的:右转一次,速度变为160,然后Flying Car向前移动2个单位长度到达起飞点,速度增加2,于是当Flying Car到达起飞点的时候,最大的速度为162。

【数据规模】

对于100%的数据

4<=h<=30

4<=w<=30

1<=v<=10000

调了老半天

 

AC代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=35;
int ans,ex,ey,f[N][N][4];
char mp[N][N];
void dfs(int x,int y,int dr,int n,int last){
    if(n<0) n=0;
    if(f[x][y][dr]>=n) return ;
    if(f[x][y][dr]<n) f[x][y][dr]=n;
    if(x==ex&&y==ey){ans=max(ans,f[x][y][dr]);return ;}
    if(n<=ans-31) return ;
    if(dr==0){//面向东 
        if(mp[x][y+1]=='#') dfs(x,y+1,0,n+1,0);
        if(mp[x-1][y]=='#'&&last!=3) dfs(x,y,1,n-35,0);
        if(mp[x+1][y]=='#'&&last!=1) dfs(x,y,3,n-40,0);
        if(mp[x][y+1]=='.'&&mp[x+1][y]=='.'&&mp[x-1][y]=='.') dfs(x,y,2,0,0);
    }
    else if(dr==1){//面向北 
        if(mp[x-1][y]=='#') dfs(x-1,y,1,n+1,1);
        if(mp[x][y-1]=='#'&&last!=0) dfs(x,y,2,n-35,1);
        if(mp[x][y+1]=='#'&&last!=2) dfs(x,y,0,n-40,1);
        if(mp[x-1][y]=='.'&&mp[x][y-1]=='.'&&mp[x][y+1]=='.') dfs(x,y,3,0,1);
    }
    else if(dr==2){//面向西 
        if(mp[x][y-1]=='#') dfs(x,y-1,2,n+1,2);
        if(mp[x+1][y]=='#'&&last!=1) dfs(x,y,3,n-35,2);
        if(mp[x-1][y]=='#'&&last!=3) dfs(x,y,1,n-40,2);
        if(mp[x][y-1]=='.'&&mp[x+1][y]=='.'&&mp[x-1][y]=='.') dfs(x,y,0,0,2);
    }
    else if(dr==3){//面向南 
        if(mp[x+1][y]=='#') dfs(x+1,y,3,n+1,3);
        if(mp[x][y+1]=='#'&&last!=2) dfs(x,y,0,n-35,3);
        if(mp[x][y-1]=='#'&&last!=0) dfs(x,y,2,n-40,3);
        if(mp[x+1][y]=='.'&&mp[x][y+1]=='.'&&mp[x][y-1]=='.') dfs(x,y,1,0,3);
    }
}
int main(){
    int n,m,v,sx,sy,d;
    memset(f,-1,sizeof f);
    scanf("%d%d%d",&n,&m,&v);
    for(int i=1;i<=n;i++) scanf("%s",mp[i]+1);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(mp[i][j]=='E'){
                mp[i][j]='#';
                sx=i;sy=j;
                d=0;
            }
            if(mp[i][j]=='N'){
                mp[i][j]='#';
                sx=i;sy=j;
                d=1;
            }
            if(mp[i][j]=='W'){
                mp[i][j]='#';
                sx=i;sy=j;
                d=2;
            }
            if(mp[i][j]=='S'){
                mp[i][j]='#';
                sx=i;sy=j;
                d=3;
            }
            if(mp[i][j]=='F'){
                mp[i][j]='#';
                ex=i;ey=j;
            }
        }
    }
    dfs(sx,sy,d,v,d);
    for(int i=0;i<4;i++) ans=max(ans,f[ex][ey][i]);
    printf("%d",ans);
    return 0;
}

 

 

posted @ 2016-10-05 20:47  神犇(shenben)  阅读(237)  评论(0编辑  收藏  举报