Pascal转C++练习题
题1之前:
1. 掌握memset用法(头文件cstring)
跟Pascal的fillchar一样,带入三个参数,memset(数组,值,大小),举个例子,将数组a全部赋值为0:memset(a,0,sizeof(a)); 中间的值和Pascal一样,可以带十六进制,C++中以0x开头的为十六进制数(Pascal是$),如:
C++ Pascal
memset(a,0x07,sizeof(a)) fillchar(a,sizeof(a),$7);
2. for循环
for(赋初值(即循环之前干的事); 继续循环的条件 ;每循环一次后干的事)
如从1~n循环
for(int i=1;i<=n;i++)
如(动规中)从1~n循环,每次01滚动
for(int i=1,int t=0;i<=n;i++,t=1-t)
解释一下,上面这一大句就是首先定义一个i赋值为1,定义一个t赋值为0,然后循环条件不再多说,后面i++不解释,t=1-t就可以实现01滚动(t=0时1-t=1,t=1时1-t=0),这样调用f[t]就相当于调用f[i%2]或者f[i&2]了(&是位运算‘与’)
3. max和min的写法,掌握问号表达式
当然可以学Pascal那样写一个函数
int max(int a,int b)
{
if(a>b) return a;
return b;
}
C++有一个问号表达式,格式是 a?b:c,表示如果a是true,那么就执行并返回b,否则返回c,这样刚才的函数就可以写成
int max(int a,int b)
{ return a>b?a:b; }
基于这个,我们写min和max又何必写成函数呢?就可以用宏来解决,就可以写成(宏的定义属于程序的预处理,要加在程序最开头、头文件之下)
#define max(a,b) a>b?a:b;
但是,上面这样是错误地,比如我们调用max(1+2,1+1),它就会直接替换成1+2>1+1?1+2:1+1,按照运算顺序就成了1+((2>1+1)?1+2:1+1),所以最后就会出错,应该加上括号,写成
#define max(a,b) (a)>(b)?(a):(b)
我们在调用一下max(2,1)*3,就直接替换成了2>1?2:1*3,最后的答案是2!看看运算顺序((2>1)?2:1*3),但是我们期待的顺序是((2>1)?2:1)*3,所以在最外面加上括号也是必须的!标准写法应为
#define max(a,b) ((a)>(b)?(a):(b))
同理可以写出min的
#define min(a,b) ((a)<(b)?(a):(b))
4. 其他基本语法
造路行动(road.pas/c/cpp/in/out)
题目描述
学校某日突发奇想,要造个小公园。但是,公园造造简单,最麻烦的就是路了。学校张榜:谁设计一个方案,材料费最小,那么,他就获得1000奖学金。鄙人想去,但是作业铺天盖地,根本没时间啊。只好到网上来求助……
各路英雄,帮帮忙吧。
输入格式
第1行,二个数,N,M。N表示公园有N个景点,M表示规划的可以造路的路的条数
接下来M行,每行3个数:X,Y,A。表示第X个景点和第Y个景点之间可以造路,材料费为A。(第X个景点和第Y个景点之间可以造路,也就是说第Y个景点和第X个景点之间也可以造路)。
当然,不会出现孤立的景点。可能有重边!!!矩阵先判断再存
数据范围:0 <N<=1000,0<M<=N*(N-1),0 <X,Y<=N,0 <A<32768。
输出格式
一个数,表示最少的材料费。
样例输入
8 13
1 7 1
1 2 9
1 6 9
2 8 2
2 3 9
3 8 3
3 4 9
4 8 4
4 5 9
5 7 5
5 6 9
6 7 6
7 8 7
样例输出
28
题2之前:
1. Pascal的Record在C++中如何定义?C++中是结构体struct
struct node{int x,y,z;};
这样就定义了一个名为node的类型,包含x,y,z三个longint
操作和Pascal几乎一样,比如
node a;//定义一个a,为node类型
a.x=1; a.y=2; a.z=3;
2. stl队列操作
加上头文件#include<queue>,由于是stl,要开放using namespace std;
声明:
queue<node> q;
就开了一个可以储存node的队列,下面对比一下C++和Pascal要好理解些
| C++ | Pascal |
声明 | queue<node> q; | q:array[0..maxn] of node; |
入队 | q.push(x); | procedure inq(node x) begin inc(r); q[r]=x; end; |
取队首第一个 | node x=q.front(); | var x:node; x=q[l+1]; |
第一个弹出 | q.pop(); | inc(l); |
判断队空 | q.empty() 队不为空返回true | l<r 队不为空时为true |
宽搜找到答案用exit(0);结束整个程序,需要包含头文件cstdlib
3. 字符操作
读入数据时候涉及到字符操作,用%c读入单个字符,比如读入单个字符到ch可写成
先定义char ch;
scanf(“%c”,&ch);
判断ch是否为’1’,应写为if(ch==’1’)...
注意是两个等号!1由于是单个字符,用单引号!
读入字符串用%s,定义为char数组
char ch[100];//定义一个长度最大为100的字符串数组
scanf(“%s”,ch);
没有分号了,因为ch为一个数组,ch就表示ch[0]的地址,如果不会字符操作,参考下面的读入模块
题目:紧急援救(bfs.pas/c/cpp/in/out)
题目描述
话说2007年8月5日,Mike博士神秘失踪了,最后发现是被外星人绑架了,幸好外星人目前还是在地球上活动,并且知道外星人不了解地球,幸好,Milk博士身上有无线信号发送装置,我们终于确定了他的位置,必须赶快到那里去救他。
根据无线信号发送装置,我们确定出一张地图,为了尽快寻找到Mike博士,于是这个光荣和艰巨的任务便交给了你,编写程序,通过使用一张地图帮助研究所确定从研究所出发找到Mike博士最短距离。
数据范围: n<=1000
输入格式
第一行为n
第二行为n*n的地图(其中0表示通路,1表示死路)
最后两行每行有两个数字,分别表示研究所的坐标和博士信号所在的位置。
输出格式
一个数字k,表示从研究所出发找到Milk博士的最短距离。
样例输入
10
0100110100
0001110010
1000000001
1000100011
0000101100
1000001100
1001010011
0000010100
0101010000
1001000001
1 7
10 2
样例输出
14
题3之前:
果子合并写法很多,可以用双队列(上一题就是队列操作,所以不再使用),练习一下堆
堆在C中为heap,但是由于其操作过于繁琐(有兴趣的自己百度看看),所以在C++中出现了一个基于队列的东东,叫做优先队列,可以直接把它当做堆就行了
头文件,既然是基于队列的,那么头文件不用说,是
#include<queue>
队列的声明是queue<类型> q;而优先队列就要在前面加上优先的单词priority,定义为
priority_queue<类型> q;
比如 果子合并这一题就需要定义priority_queue<int>q;//默认大根堆
还是列一个表,但是Pascal的就不打了(我不会了。。。)
| C++表达式 | |
头文件 | #include<queue> | |
定义 | 大根堆 | priority_queue<int> q; 由于默认就是大根堆,所以不需要家任何参数,或者可以写全 priority_queue<int,vector<int>,less<int> > q; 注意,最后两个‘>’间必须有一个空格,不然会让编译器误认为是位运算右移符号‘>>’ vector是动态数组,一般不推荐使用(操作不直观,某些时候会变慢) 好像只有优先队列是相反的,大根堆要用less(英文是‘更小’)定义 |
小根堆 | 这里就必须要带上参数了 priority_queue<int,vector<int>,greater<int> > q; 同理,小根堆用greater定义 | |
入队 | q.push(x); | |
取队首元素 | int x=q.top();//唯一不同之处 | |
弹出队首 | q.pop(); |
然后还有排序,排序会用到算法库(头文件algorithm),算法库的详解可以看《C++ Primer》一书,这里只说说sort,也就是排序
如果我们需要排序的为一个数组a,从1~n排序,从小到大
sort(a+1,a+1+n);//默认是从小到大
第一个参数a+1表示a数组中a[1]的地址,等同于&a[1],a+1+n表示a数组中a[n+1]的地址,等同于&a[n+1],由于C++的stl全部采用左闭右开的区间,所以上面的右界应是a[n+1]。那么上面一句话就等同于sort(&a[1],&a[n+1]);但是不推荐,后面a[n+1]容易打成a[n]!
如果要从大到小就需要写一个比较函数,假设定义为cmp,就写成
sort(a+1,a+1+n,cmp);
在调用之间定义比较函数cmp
bool cmp(int a,int b) { return a>b; }
基于比较函数,我们就可以很轻松地写出双关键字排序了,假设我们读入n组数据,每组有x,y两个数,按照x从大到小排序,x相等时按照y从小到大排序
先定义结构体 struct node{int x,y;};然后用node定义数组a,读入数据
sort(a+1,a+1+n,cmp);
在这之前定义比较函数
bool cmp(node a,node b)
{
if(a.x==b.x) return a.y<b.y;
return a.x>b.x;
}
以此类推就可以写出n关键字排序了
在用sort的时候根本不用担心效率问题,它是融合了几种排序算法,是永远卡不到的(除非本来就要超时。。。。)
合并果子(fruit.pas/dpr/c/cpp/in/out)
【问题描述】
在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。
每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。
因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。
例如有3种果子,数目依次为1,2,9。可以先将1、2堆合并,新堆数目为3,耗费体力为3。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为12,耗费体力为12。所以多多总共耗费体力=3+12=15。可以证明15为最小的体力耗费值。
【输入文件】
输入文件fruit.in包括两行,第一行是一个整数n(1<=n<=10000),表示果子的种类数。第二行包含n个整数,用空格分隔,第i个整数ai(1<=ai<=20000)是第i种果子的数目。
【输出文件】
输出文件fruit.out包括一行,这一行只包含一个整数,也就是最小的体力耗费值。输入数据保证这个值小于231。
【样例输入】
3
1 2 9
【样例输出】
15
【数据规模】
对于30%的数据,保证有n<=1000:
对于50%的数据,保证有n<=5000;
对于全部的数据,保证有n<=10000。
题4之前:
前面最小生成树已经练了矩阵,这一题就spfa,用链表写!
链表操作要用到前面所说的结构体,就像Pascal会用到Record一样。
比如我们定义一个链表,需要储存点y,权值z,和下一个指针,就要写成
| C++ | Pascal |
定义 | struct link{int y,z;link* next;}; | type pnode^=tnode; tnode=record y,z:longint; next:pnode; end; //应该就是这样吧。。。。 |
声明一个链表 | link *head[MAXN]; | first:array[0..maxn] of pnode; |
插入 | void insert(int x,int y,int z) { link *node=new link; node->y=y;node->z=z; node->next=head[x]; head[x]=node; } | procedure insert(x,y,z:longint); var p:pnode; begin new(p); p^.y:=y;p^.z:=z; p^.next=first[x]; first[x]=p; end; |
判断指针node是否为空,不为空返回true | if(node) //在C++中只要一个不为0的值就可作bool返回true | if(node<>nil) |
说明 | 在C++中,在变量名之前加一个*说明该变量是一个地址,加星号表示引用其内容 |
|
| C++中结构体用’.’指向内部元素,如a.x 如果是链表中,指针就要变为’->’,如node->x | Pascal同C++,Record也用’.’指向内部元素,如a.x Pascal中地址指向则变为’^.’,如node^.x |
题目:星门跳跃(jump.pas/c/cpp/in/out)
题目描述
在EVE游戏中,宇宙被划分成为许多区域,每个区域中都有数目不定的星门,可以通过星门来跳跃到特定的区域(星门是双向的)。
现在你正参与BBE联军与MLGBD联盟的会战,但由于飞船受损,需要尽快回到后方的友军空间站进行维护。
试编写程序,计算出所须的最短的返回空间站时间。
为了简化问题,我们约定飞船所在的位置为区域1,空间站所在的位置为区域N。
问题规模:
对于100%的数据,1<N<=10000,1<M<20000,1<=X[],Y[]<=N,1<=Z[]<=100;
输入格式
第1行,两个整数N,M,分别为区域的总数和星门的总数;
第2..M+1行,每行三个整数X[i],Y[i],Z[i],分别为星门连接的两个区域,以及跳跃所需时间;可能有重边!
输出格式
一个整数,返回空间站所需的最短时间。无法返回输出’NO’
样例输入
5 3
1 4 5
4 5 1
1 2 7
样例输出
6