GRYZ[寒假模拟赛]
GRYZ娱乐时刻
【题目描述】
无聊的hyxzc不想写代码了,于是他开始玩游戏——洛克王国。众所周知,洛克王国是一个非常好玩的游戏(至少在hyxzc眼中是这样的)。这天,hyxzc登上他的洛克王国账号,开始了新的一天的颓废之旅。
hyxzc是一个高傲的人,他想把自己的宠物都升到100级(没办法,强迫症),今天是洛克王国4周年纪念日,所以奖励非常多,正当小洛克们欢快的庆祝周年的时候,坏坏的恩佐又出来捣乱了,(众所周知,恩佐是一个超级大坏蛋,总想一些办法去损害洛克王国,而守护洛克王国是每位小洛克的责任)。这次,恩佐无意在黑魔法中发现了召唤远古恶龙的方法。并且召唤了n条恶龙,而你的任务则是消灭这n条恶龙, 本次任务奖励有大量经验,能够让宠物更快的升级,所以hyxzc便心动了。
hyxzc一共有m个宠物可以召唤,而每个宠物的等级各不相同,等级为x的宠物只能干掉小于等于x的恶龙,且每只宠物只能干掉一只恶龙,因为宠物还要去找自己的小伙伴去玩耍呢,并且你需要花费x个洛克贝为宠物恢复活力。hyxzc可不是一个大方的家伙,他希望花最少的洛克贝来完成这个任务。而洛克王国的防沉迷告诉hyxzc,他只有1秒钟的时间去思考如何召唤宠物,于是hyxzc便向你求助,你只需要输出他的最少花费即可,若无法完全杀掉恶龙,则输出“Loowater is doomed!”。
【输入格式】
输入包含T组数据,每组数据的第一行为正整数n和m;以下n行每行为一个整数,即恶龙的等级,以下m行为一个整数,即每个宠物的等级,输入结束标记为n=m=0;
【输出格式】
对于每组数据,输出最少花费。
【样例输入】
2 3
5
4
7
8
4
2 1
5
5
10
0 0
【样例输出】
11
Loowater is doomed!
【数据范围】
0
对于20%的数据:0<=20;0<=100000;
对于40%的数据:0<=200;0<=100000;
对于60%的数据:0<=2000;0<=100000;
对于100%的数据:0<=20000;0<=100000;
GRYZ追击
自己的答案(贪心算法);
#include
#include
using namespace std;
#include
#include
int n,m;
int el[20001],cw[20001];
void px(int n,int m)
{
sort(el+1,el+n+1);
sort(cw+1,cw+m+1);
}
int main()
{
freopen("hyxzc.in","r",stdin);
freopen("hyxzc.out","w",stdout);
while(scanf("%d%d",&n,&m)==2&&(n!=0&&m!=0))
{
long long sum=0;
memset(el,0,sizeof(el));
memset(cw,0,sizeof(cw));
for(int i=1;i<=n;++i)
scanf("%d",&el[i]);
for(int i=1;i<=m;++i)
scanf("%d",&cw[i]);
px(n,m);
int ell=1,cwl=1;
while(ell<=n&&cwl<=m)
{
if(el[ell]<=cw[cwl])
{
sum+=cw[cwl];
ell++;
cwl++;
}
if(el[ell]>cw[cwl]&&cw[cwl]!=0)
{
cwl++;
}
}
if(ell==n+1)
cout<<sum<<endl;
if(cwl==m+1&&ell<=n)
printf("Loowater is doomed!\n");
}
fclose(stdin);
fclose(stdout);
return 0;
}
GRYZ追击时刻
XYD过完年后高高兴兴的回到了GRYZ,然后他发现可爱的Robot已经在这里等待了3天,由于Robot跑的很慢,所以她正在准备施展魔法,逮住 XYD。
XYD知道,除了男生宿舍,其他的地方都会被Robot宝宝魔法控制(因为宝宝是一个可爱的女孩子),如果XYD被控制之后,就会发生很可怕的 事情。。。
所以,XYD一定要尽快赶回男生宿舍。
GRYZ可以用一个N*M(N,M<=50)的地图表示,地图上有5种符号:"X S D . *" 。其中“X”处有可怕的兔兔(兔兔可能很多),XYD和Robot都不能经过。
"."表示XYD和魔法都能经过的地方。
“*”表示Robot的位置,“S”表示XYD起始位置,“D”表示男生宿舍。
xyd每秒钟可以向相邻位置移动,Robot的魔法也会向相邻的地方蔓延(从已覆盖的区域,开始只覆盖*点)。众所周知,宝宝魔法就像是一股水流。
求XYD回到男生宿舍的最短时间,如果XYD回不到男生宿舍,就有可能被迫以身相许,那么他就会高兴的大喊一声“I Love xxx!!!”。(这就是很可怕的事情)
【输入格式】
第一行为正整数n和m;以下n行m列为地图。
【输出格式】
如果能成功回到男生宿舍输出最短时间,否则输出“I Love xxx!!!”(不包括双引号)
【样例输入】
3 3
D.*
…
.S.
【样例输出】
3
【样例输入】
3 3
D.*
…
..S
【样例输出】
I Love xxx!!!
自己的答案(正确):
#include
using namespace std;
#include
#include
#define M 55
int map[M][M],head=0,tail=0,q[M*M][2];
int xx[4]={0,0,1,-1};
int yy[4]={1,-1,0,0};
int tim[M][M],bu[M][M];
int n,m,xk,yk,xz,yz;
void input()
{
scanf("%d%d",&n,&m);
char ch[M];
memset(tim,99,sizeof(tim));
for(int i=1;i<=n;++i)
{
scanf("%s",ch+1);//从ch[1]读入字符串,scanf不读入回车和字符
for(int j=1;j<=m;++j)
{
if(ch[j]=='.')
map[i][j]=0;
if(ch[j]=='*')
{
tail++;
q[tail][0]=i;//队列储存着
q[tail][1]=j;
tim[i][j]=0;
}
if(ch[j]=='S')//起始点
{
xk=i;
yk=j;
}
if(ch[j]=='D')//终点
{
map[i][j]=1;
xz=i;yz=j;
}
if(ch[j]=='X')
{
map[i][j]=2;
}
}
}
}
void search_time()
{
while(head
{
head++;
for(int i=0;i<4;++i)//4种走的情况
{
int nx=q[head][0]+xx[i],ny=q[head][1]+yy[i];
if(nx&&ny&&nx<=n&&ny<=m&&!map[nx][ny]&&tim[nx][ny]>tim[q[head][0]][q[head][1]]+1)
{
tim[nx][ny]=tim[q[head][0]][q[head][1]]+1;//更新每个点洪水到达最短时间
tail++;
q[tail][0]=nx;
q[tail][1]=ny;
}
}
}
}
void search_bu()
{
q[1][0]=xk;//队列开始存储人走的路径
q[1][1]=yk;
memset(bu,99,sizeof(bu));//把步数赋值一个大数,好进行下面的更新
bu[xk][yk]=0;
head=0;
tail=1;
while(head
{
head++;
if(q[head][0]==xz&&q[head][1]==yz)
break;
for(int i=0;i<4;++i)
{
int nx=q[head][0]+xx[i];
int ny=q[head][1]+yy[i];
if(nx&&ny&&nx<=n&&ny<=m&&map[nx][ny]<2&&bu[nx][ny]>bu[q[head][0]][q[head][1]]+1&&tim[nx][ny]>bu[q[head][0]][q[head][1]]+1)//虽然说人比魔法先到该点,但是当魔法到来的时候,人还没有到下一个点,这样还是不行
{
bu[nx][ny]=bu[q[head][0]][q[head][1]]+1;
++tail;
q[tail][0]=nx;
q[tail][1]=ny;
}
}
}
if(bu[xz][yz]==1667457891)//前面赋值的99的真实值
printf("I Love xxx!!!");
else printf("%d",bu[xz][yz]);
return;
}
int main()
{
freopen("clikar1.in","r",stdin);
freopen("clikar.out","w",stdout);
input();
search_time();
search_bu();
fclose(stdin);
fclose(stdout);
return 0;
}
GRYZ就餐时刻
【题目描述】
寒假,大家都回家过年去了,只有GRYZ苦逼的竞赛生们还在学校上课。众所周知,有人的地方就需要有饭,但是食堂的大爷们都回家了,我们只能依靠外卖。已知那是一个非常大的外卖店,有专业的盒饭生产设备,为了保证GRYZ的孩子们每顿饭能吃好吃的饭菜,它们总会将a点生产出的盒饭运往加热处加热后再运往b点装车。这些部门非常的高能,它们有时可以生产盒饭,有时又能变身成装车点(不要问我为什么)。
有些部门之间有专门的传送带连接,店长是个非常珍惜时间的人,他希望盒饭从生产出来到运走所花费的时间尽可能的短,但是店长又是一个超级懒人,所以他把计算的工作交给了你
【输入格式】
第一行两个整数n、m,n表示部门数量,m表示传送带数量。出于方便,1号部门是加热处。
接下来m行,每行三个整数u、v、w,表示有一条从u部门到v部门的传送带,传送过去需要w个单位时间。注意传送带是单向的。
接下来一个整数q,表示有q次运送。
接下来q行,每行两个数a、b,表示这一次要将产品从a部门运送到b部门。
【输出格式】
输出q行,每行一个整数,表示这次运送最少需要的时间。若没有传送方案,输出-1。
【样例输入】
5 5
1 2 3
1 3 5
4 1 7
5 4 1
5 3 1
3
4 2
5 3
2 3
【样例输出】
10
13
-1
【数据规模与约定】
30%的数据,n≤100,m≤500,w=1
60%的数据,n≤100,m≤5000
另20%的数据,q=1
100%的数据,2≤n≤3000,m≤100000,2≤a,b≤n,
q≤100000,1≤u,v≤n,1≤w≤10000
有些部门之间可能有多条传送带。
边表:一条边里储存着指向同一起点的上一条边,是边指向边
邻接表:点指向点,1—>3à5,表示1-3,和1—5这两条边,
由点指向点,好理解些
答案:
#include
using namespace std;
#include
#include
#define M 100001
#define N 3001
#define maxx 999999
struct Edge{
int u,v,w,next;
};
Edge edge1[M],edge2[M];
int dis1[N],dis2[N];
int n,m,head1[N],head2[N];
int visit1[N]={0},visit2[N]={0};
void add1(int,int,int,int);
void add2(int,int,int,int);
void djk();
void input();
void sc();
int main()
{
freopen("eat.in","r",stdin);
freopen("eat.out","w",stdout);
memset(dis2,127,sizeof(dis2));
memset(dis1,127,sizeof(dis1));
input();
djk();
sc();
fclose(stdin);
fclose(stdout);
return 0;
}
void input()
{
scanf("%d%d",&n,&m);
int u1,v1,w1;
for(int i=1;i<=m;++i)
{
scanf("%d%d%d",&u1,&v1,&w1);
add1(u1,v1,w1,i);
add2(v1,u1,w1,i);
}
return;
}
void sc()
{
int q,a,b;
scanf("%d",&q);
for(int i=1;i<=q;++i)
{
scanf("%d%d",&a,&b);
if(dis1[b]+dis2[a]
printf("%d\n",dis1[b]+dis2[a]);
else printf("-1");
}
return;
}
void add1(int u1,int v1,int w1,int i)
{
edge1[i].u=u1;
if(u1==1)
dis1[v1]=w1;
edge1[i].v=v1;
edge1[i].w=w1;
edge1[i].next=head1[u1];
head1[u1]=i;
}
void add2(int u1,int v1,int w1,int i)
{
edge2[i].u=u1;
if(u1==1)
dis2[u1]=w1;
edge2[i].v=v1;
edge2[i].w=w1;
edge2[i].next=head2[u1];
head2[u1]=i;
}
void djk()
{
dis1[1]=0;
for(int i=1;i<=n-1;++i)
{
int min1=maxx,k=0;
for(int j=1;j<=n;++j)
{
if(dis1[j]
{
k=j;
min1=dis1[j];
}
}
if(k==0) break;
visit1[k]=1;
for(int l=head1[k];l!=0;l=edge1[l].next)
{
if(dis1[edge1[l].v]>dis1[edge1[l].u]+edge1[l].w)
dis1[edge1[l].v]=dis1[edge1[l].u]+edge1[l].w;
}
}
dis2[1]=0;
for(int i=1;i<=n-1;++i)
{
int min1=maxx,k=0;
for(int j=1;j<=n;++j)
{
if(dis2[j]
{
k=j;
min1=dis2[j];
}
}
if(k==0) break;
visit2[k]=1;
for(int l=head2[k];l!=0;l=edge2[l].next)
{
if(dis2[edge2[l].v]>dis2[edge2[l].u]+edge2[l].w)
dis2[edge2[l].v]=dis2[edge2[l].u]+edge2[l].w;
}
}
}