试题名称 | 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; }