题目名称 

彩色穿孔卡片

艾萨拉的激流

阿鲁高的阴谋

潜入辛迪加

源文件名(.c/.cpp/.pas) 

punch

azshara

arugal

syndicate

输入文件名 

punch.in

azshara.in

arugal.in

syndicate.in

输出文件名 

punch.out

azshara.out

arugal.out

syndicate.out

时间限制(s) 

1

1

1

1

空间限制(MB) 

512

512

512

512

 

比赛说明

l  本次比赛所用题目全部系BYVoid独家原创,转载必须注明作者。

l  比赛所有题目背景均来自《魔兽世界》,本人在其故事上进行再创作。

l  请勿在现实生活中模仿故事中任何人物的行为。

l  所有题目中涉及到的整数运算,均不超过32位带符号整型范围。


彩色穿孔卡片

问题描述

“在逃离诺莫瑞根的时候,我们留下了太多的数据!非常重要的数据!”大机械师卡斯派普十分着急地说,“尽管我们已经从矩阵打孔计算机上拿回了许多彩色穿孔卡片,但是混乱的数据令人无法忍受!”

 

自从诺莫瑞根陷落以后,侏儒们一直寄居在铁炉堡中。大机械师卡斯派普花了不少钱来悬赏勇士们去诺莫瑞根替他取回一些卡片,现在他已经有了一大堆彩色穿孔卡片。但是这些卡片都是残缺不全的,有的甚至还是无效的,想从这些破烂中恢复数据,实在是一件不容易的事。卡斯派普发现每个卡片的开头和结尾都有标记,记录着它原本在矩阵打孔计算机中序列的位置,于是想出了一个恢复数据的方法。把每张卡片看成数轴上的一条线段,开头和结尾的标记A,B为数轴上的两个点。卡斯派普按拿到的顺序把卡片一张一张地贴到数轴上,每张卡片的颜色都不同。他想知道贴完卡片以后的数轴上一共有多少种不同的颜色。卡斯派普请你帮助他写一个程序来解决这个问题。

 

 

输入格式

l  第1行:一个整数N,表示卡斯派普收集到的卡片的数量。

l  第2行至第N+1行:第i+1行给出了第i张卡片的头尾两个标记Ai,Bi,贴卡片的顺序与输入文件中出现的先后顺序一致。

 

输出格式

l  一个整数,表示卡斯派普能在数轴上看到的不同的颜色的数目。

 

样例输入

4

0 5

3 8

5 6

4 7

 

样例输出

3

 

样例说明

如图所示

 

 

 

可以看到的不同颜色的卡片数为3,3号卡片被4号卡片所覆盖。

 

数据规模

50%的数据满足N<=1,000; 0<=Ai<Bi<=100,000(1<=i<=N);

100%的数据满足N<=20,000; 0<=Ai<Bi<=1,000,000,000(1<=i<=N)。

 

 

#include<cstdio>
#define maxn 20010
int n,i;
int x[maxn],y[maxn];
bool v[maxn];
int ans;
void make(int t,int l,int r)
{
     while (t<=n&&(x[t]>r||y[t]<l)) t++;
     if (t>n) 
     {
              if (l<r) v[i]=true;
              return;
     }
     if (x[t]>l) make(t+1,l,x[t]);
     if (y[t]<r) make(t+1,y[t],r);
}
int main()
{
    freopen("punch.in","r",stdin);
    freopen("punch.out","w",stdout);
    scanf("%d\n",&n);
    for (i=1;i<=n;i++) scanf("%d %d\n",&x[i],&y[i]);
    for (i=n;i>0;i--) make(i+1,x[i],y[i]);
    for (i=1;i<=n;i++)
      if (v[i]) ans++;
    printf("%d\n",ans);
    return 0;
}

 

艾萨拉的激流

问题描述

沿着卡利姆多北方边界延展的破碎的海岸,在世界大分裂之前曾经是暗夜精灵首都艾萨琳的一部分,艾萨拉。恶魔从这个世界被消除,这片土地被撕碎并被大海吞没,剩下的只有曾经雄伟城市的废墟。自那以后,这个岩石交错的岛屿、峭壁悬崖和珊瑚丛生的海洋成为许多传说来源。暗夜精灵们认为这是个被诅咒的地方,连经验最丰富的船长都从这里绕行。这里有巨大的水生物,可怕的暗礁,强大的激流与巨浪。然而传闻这里水下有着惊人的宝藏,吸引了一支矮人探险队前来。矮人们经过多日的探险,终于发现了在一个水域下面有着未知的宝藏。但是这个海域常常有着激流与巨浪,矮人们不可能把探险艇停下来甚至逆流而上。

 

这个海域可以被描述为一个W×L的矩形,分成个一个个单元格。每个单元格代表的海域下面可能是宝藏,也可能是一块可怕地礁石。从激流的上游开始,每过1秒探险艇就会被冲往下游的一个单位。在被冲往下游的过程中,矮人们可以控制方向,选择他的正前,左前边,或右前边的一个单位。矮人们决定从这个激流的最上游的任意一个单元格开始向下漂流,每经过一个单元格就可以取走这个单元格上的宝藏。但是千万不能碰到礁石,否则他的探险艇会支離破碎。请你安排一个计划,算出探险队最多一共能拿到多少宝藏。

 

输入格式

l  第1行,两个整数W,L。

l  接下来的L行,每行W个整数,以“从上游到下游,面朝水流方向从左向右”的顺序依次为每个单元格中的宝藏的数目,如果为-1则表示这个单元格是礁石。

 

输出格式

l  一个整数,表示得到的宝藏。

 

样例输入

3 5

5 1 3

-1 7 -1

5 1 10

4 -1 7

20 10 5

 

样例输出

41

 

样例说明

上游->下游

1

2

3

4

5

1

5

-1

5

4

20

2

1

7

1

-1

10

3

3

-1

10

7

5

 

如上表,探险队从(1,1)开始,第1秒向右转一下,被冲到(2,2)。第2秒向左转一下,被冲到(3,1)。接下来第3秒正前行走,经过(4,1),(5,1),一共拿到5+7+5+4+20=41个单位的宝藏。

数据规模

1<=W<=1000

1<=L<=10000

所有涉及到的数字不会超过32位带符号整型的范围

 

 

#include<cstdio>
#include<cstring>
#include<iostream>
#define maxw 1001
#define maxl 10001
using namespace std;
int w,l;
int a[maxl][maxw];
int f[maxl][maxw];
int ans;
int main()
{
    freopen("azshara.in","r",stdin);
    freopen("azshara.out","w",stdout);
    scanf("%d %d\n",&w,&l);
    for (int i=1;i<=l;i++)
    for (int j=1;j<=w;j++)
    {
        scanf("%d",&a[i][j]);
    }
    for (int i=1;i<=l;i++)
    for (int j=1;j<=w;j++)
    if (a[i][j]!=-1)
    {
        if (j>1&&a[i-1][j-1]!=-1) f[i][j]=max(f[i-1][j-1]+a[i][j],f[i][j]);
        if (j<w&&a[i-1][j+1]!=-1) f[i][j]=max(f[i][j],f[i-1][j+1]+a[i][j]);
        if (a[i-1][j]!=-1) f[i][j]=max(f[i-1][j]+a[i][j],f[i][j]);
        ans=max(ans,f[i][j]);
    }
    printf("%d\n",ans);
    return 0;
}

 

 

阿鲁高的阴谋

问题描述

我尝流连于格雷迈恩之墙,叹息着轻抚隔世的沧桑。

我曾徜徉于洛丹米尔的水,飘离在腐败的气息之上。

卫道士有卫道士的避风港,叛节者有叛节者的理想乡。

魔法师有魔法师的墓志铭,造物主有造物主的礼拜堂。

影牙城堡的主人,执着于疯狂。

牙将被诅咒磨砺,影终被黑夜深藏。

我曾抬头看着银松穹顶的冷光,血月的辉耀隐约中露出寒芒。

巨大的引力牵动着星辰的轨道,谁又看得到这个世界的真相。

 

在第三次战争中,达拉然被燃烧军团彻底催化。曾经是肯瑞托的一名成员的阿鲁高,在不断的失败和恐惧中,召唤了远古的恶魔——贪婪而又凶猛的沃根。沃根恐怖的力量很快清理了附近的亡灵天灾,但是它也开始对肯瑞托发起了攻击。可悲的是,阿鲁高也堕入了恶魔力量的深渊,他把附了沃根魔法的手腕强加在自己的朋友手上,让他们变成了奴仆。一个夜晚,阿鲁高带领沃根悄悄穿越格雷迈恩之墙,进攻了影牙城堡。原来辉煌的城堡,顷刻间被阴影和血腥味所笼罩。隐身于城堡内高高的塔顶不断扩充自己的军队,幻想有一天可以成为这片大陆的主人。终于有一天,巫妖王剥夺了阿鲁高死亡的权利,把阿鲁高变成了他当年痛恨的敌人,亡灵天灾。在诺森德,阿鲁高建立了血月神教,领导狼人们成为了天灾军团的爪牙。在灰陵的海岸上,阿鲁高建立了第一个据点,并让手下变成人形骗取了联盟军团的信任。

 

银溪镇的追随者们为阿鲁高制造了一个船,用于在海岸上扩张。在漫长的旅途中,阿鲁高必须消耗法力创造结界以存储燃料。在途中每一天,阿鲁高都可以驶到一个联盟港口骗取燃料,代价是消耗法力维持幻象。阿鲁高的目标是寒冰皇冠,要航行T天才能到达。由于天气和海域的不同,每天航行所需的燃料消耗也不同。每天都可以到达一个联盟港口,骗取一些燃料(也可以不去,从结界中取得燃料补充所需,注意,每天的消耗必须被满足),骗取每个单位燃料需要一定的法力消耗。如果骗取的燃料除供这一天消耗外还有剩余,则必须把它存到法力结界中,但是限于结界规模,只能把不超过V的燃料存储到结界中。在结界中存储的每个单位的燃料每天会消耗掉阿鲁高的W点法力值。为了留有足够多的法力,阿鲁高必须尽量地减少法力消耗。请你算出阿鲁高到达目标最少的法力消耗是多少。

 

 

输入格式

l  第1行,四个整数,航行的天数T,结界的最大存储量V,每个港口的库存A,结界中每存储一单位燃料一天的法力消耗W。

l  第2行至第1+T行,第k+1行有两个整数,分别表示第k天的需要的燃料N[k],抢夺第k天到达的港口的每个单位燃料的法力消耗B[k]。

 

输出格式

l  第1行,最小的法力消耗。

 

l  第2行至第1+T行,第k+1行有一个整数,表示第k天到达港口后抢夺燃料的数量。如果有多种解,使每天抢夺的燃料数组成一个序列,所有这些序列构成一个集合,对这个集合进行第一位为第一关键字,第二位为第二关键字,……的多关键字排序,输出其中最小的一个即可。

 

样例输入

2 5 10 5

5 20

3 30

 

样例输出

175

8

0

 

样例说明

在第1天骗取8个单位燃料,法力消耗8*20=160。5个用于当天直接使用,3个放入结界,存储法力消耗3*5=15。在第2天不需骗取,直接使用结界中的3个单位燃料。所以总法力消耗为160+15=175。

数据规模

1<=T<=1000

1<=V,A,W,B[i]<=100

1<=N[i]<=V

 

 

C++code
#include<cstdio>
#include
<cstring>
#include
<cstdlib>
int t,v,A,w;
int n[1010],b[1010];
int f[1010][110];
int a[1010][110];
void print(int x,int y)
{
if (x==0) return;
print(x
-1,y+n[x]-a[x][y]);
printf(
"%d\n",a[x][y]);
}
int main()
{
freopen(
"arugal.in","r",stdin);
freopen(
"arugal.out","w",stdout);
scanf(
"%d %d %d %d\n",&t,&v,&A,&w);
for (int i=1;i<=t;i++) scanf("%d %d\n",&n[i],&b[i]);
memset(f,
63,sizeof(f));
f[
0][0]=0;
for (int i=1;i<=t;i++)
for (int j=0;j<=A;j++)
for (int k=0;k<=v;k++)
if (k+j>=n[i]&&k+j-n[i]<=v)
if (f[i][k+j-n[i]]>f[i-1][k]+j*b[i]+(k+j-n[i])*w)
{
f[i][k
+j-n[i]]=f[i-1][k]+j*b[i]+(k+j-n[i])*w;
a[i][k
+j-n[i]]=j;
}
printf(
"%d\n",f[t][0]);
print(t,
0);
return 0;
}

 

 

 

潜入辛迪加

问题描述

“我们最新的研究成果《毒药研究方案》被可恶的辛迪加间谍偷走了!”作为拉文霍德的一员,你一定感到很震惊,因为它是我们最尖端的科研人员的一年的研究成果。被辛迪加获得,我们可能会有灭顶之灾。狡猾的辛迪加为了躲避我们的追杀,他们并没有把《毒药研究方案》带回激流堡,而是藏了起来。但是终究是我们技高一筹,通过购买侏儒的最新研究成果“静电放射探测器”,我们已经发现了他们的藏身之地。原来他们早就在奥特兰克山脉的地下修建了一个巨大的城市,现在,他们就把《毒药研究方案》放在了城市的最深处。更好的消息是,我们已经发现了地下城的入口。作为一名出色的盗贼,你要学会以彼之道,还施彼身——把《毒药研究方案》偷回来。然而辛迪加布置了严密的防御,更糟糕的是,他们从地精购买了电磁监视器。无论你的潜行技巧有多么高明,只要一接近它,就会出发警报。只有破坏它的供电系统,才能电磁监视器悄无声息得失效。

 

现在,“静电放射探测器”已经为我们生成了一张地图,它可以告诉你整个地下城的布局结构,包括每一个电磁监视器的位置,及其供电装置的位置。辛迪加的地下城可以被描述为一个N*N的表格,城市的入口在(1,1)处,目标《毒药研究方案》在(N,N)处。每个单元格可能是一片空地、一个障碍物、一个辛迪加卫士、一个电磁监视器、或者一个的供电装置。从入口处开始,每步你只能向上、下、左、右移动到相邻的一个单元格,不可以停留在原地。你只能进入空地,或者失去供电系统的电磁监视器的位置,或者摧毁供电装置。你不能移动到障碍物上,也不能进入辛迪加卫士的视线中。辛迪加卫士可以监视自己所在单元格以及上下左右共五格的位置,而且他们的视线可以重叠。你不能杀死辛迪加卫士,也不能被他们发现。每个电磁监视器的供电装置可能存在,也可能无法破坏或者根本不存在。一个供电装置也可能会对应零个、一个或多个电磁监视器,意味着摧毁它,对应的所有电磁监视器都会失效。(1,1)和(N,N)一定是可以通行的。拉文霍德要求你在执行任务之前首先给出一个计划书,即要求算出至少一共需要多少步,才能拿到我们的《毒药研究方案》。

 

输入格式

第1行,两个整数N, M。表示地图大小为N*N,供电装置的数量为M。

第2-N+1行,每行N个整数,每个整数i可能是0,-1,-2或者一个正整数。i=0表示该位置为一块空地,i=-1表示该位置为一个障碍物,i=-2表示该位置为一个辛迪加卫士。如果i是一个属于[1,M]的正整数,则表示该位置为一个供电装置,其编号为i。如果i是一个大于M的正整数,则表示该位置为一个电磁监视器,它的电力由编号为i-M的供电装置提供。

 

输出格式

一个整数,为拿到《毒药研究方案》所需的最少的步数。

 

样例输入

6 2

0 0 0 -2 -1 2

-1 0 0 0 -1 0

-2 0 0 0 3 3

-2 0 0 -1 -1 4

0 -1 0 0 -1 0

1 0 0 0 -1 0

 

样例输出

24

 

样例说明

地图如下图,S为入口,T为目标,黑色的单元格为障碍物。每个E表示一个卫兵,(E)为卫兵的监视范围。K1表示供电装置1,K2表示供电装置2。D1表示供电装置为1的电磁监视器,D2表示供电装置为2的电磁监视器。

 

最优的路线为(1,1) →(1,2) →(2,2) →(2,3) →(3,3) →(4,3) →(5,3)→(6,3) →(6,2) →(6,1)(破坏供电1)→(6,2) →(6,3) →(5,3) →(4,3) →(3,3) →(3,4) →(3,5) →(3,6) →(2,6) →(1,6)(破坏供电2) →(2,6) →(3,6) →(4.6) →(5,6) →(6,6)

 

 

数据规模

1<=N<=50

0<=M<=16

 

C++code
1 #include<cstdio>
2 #include<cstring>
3 #include<cstdlib>
4  int di[5]={0,0,1,0,-1};
5  int dj[5]={0,1,0,-1,0};
6  int k[17]={0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};
7 int n,m;
8 int a[55][55];
9 struct node
10 {
11 int x,y,n,key;
12 }f[5000000];
13 bool v[65537][55][55];
14 int main()
15 {
16 freopen("syndicate.in","r",stdin);
17 freopen("syndicate.out","w",stdout);
18 scanf("%d%d\n",&n,&m);
19 int t;
20 for (int i=1;i<=n;i++)
21 {
22 for (int j=1;j<=n;j++)
23 {
24 scanf("%d",&t);
25 if (a[i][j]!=-1) a[i][j]=t;
26 if (t==-2)
27 {
28 if (j>1) a[i][j-1]=-1;
29 if (j<n) a[i][j+1]=-1;
30 if (i>1) a[i-1][j]=-1;
31 if (i<n) a[i+1][j]=-1;
32 }
33 }
34 scanf("\n");
35 }
36 int head=0,tail=1,x,y;
37 f[1].x=1;
38 f[1].y=1;
39 v[0][1][1]=true;
40 while (head<tail)
41 {
42 head++;
43 for (int i=1;i<=4;i++)
44 {
45 x=f[head].x+di[i];
46 y=f[head].y+dj[i];
47 t=f[head].key;
48 if (x>0&&y>0&&x<=n&&y<=n&&!v[t][x][y])
49 {
50 if (x==n&&y==n)
51 {
52 printf("%d\n",f[head].n+1);
53 return 0;
54 }
55 if (a[x][y]==-1||a[x][y]==-2) continue;
56 if (a[x][y]==0)
57 {
58 v[t][x][y]=true;
59 f[++tail].x=x;
60 f[tail].y=y;
61 f[tail].n=f[head].n+1;
62 f[tail].key=f[head].key;
63 continue;
64 }
65 if (a[x][y]>m)
66 {
67 if ((f[head].key & k[a[x][y]-m])==k[a[x][y]-m])
68 {
69 v[t][x][y]=true;
70 f[++tail].x=x;
71 f[tail].y=y;
72 f[tail].n=f[head].n+1;
73 f[tail].key=f[head].key;
74 continue;
75 }
76 }
77 if (a[x][y]<=m&&a[x][y]>0)
78 {
79 v[t][x][y]=true;
80 f[++tail].x=x;
81 f[tail].y=y;
82 f[tail].n=f[head].n+1;
83 f[tail].key=f[head].key | k[a[x][y]];
84 v[f[tail].key][x][y]=true;
85 }
86 }
87 }
88 }
89 return 0;
90 }
91