上海大学ACM集训队培训资料全Word文档格式.docx
《上海大学ACM集训队培训资料全Word文档格式.docx》由会员分享,可在线阅读,更多相关《上海大学ACM集训队培训资料全Word文档格式.docx(13页珍藏版)》请在冰豆网上搜索。
return0;
运行结果
HelloWorld!
供了很多已经写好的函数(成为C++标准库),我们做的只是拿来用就可以了。
第二行的
“usingnamespacestd;
”是使用标准命名空间,因为我们在程序中用到了在标准命名空间里的函数和对象。
目前可以不了解其具体如何实现,在以后的程序设计中可以再对其进行了解。
在明函数中“cout<
”HelloWorld!
”<
”是在屏幕上打印“HelloWorld!
”,“endl”表明打印完这句话之后需要换行。
如果我们替换引号内的内容,程序的输出就会相应改变。
另外一个C++程序例子
//ourfunc.cpp--definingyourownfunction
#include<
voidsimon(int);
//functionprototypeforsimon()
intmain()
usingnamespacestd;
simon(3);
//callthesimon()function
cout<
"
Pickaninteger:
;
intcount;
cin>
>
count;
simon(count);
//callitagain
Done!
<
endl;
return0;
voidsimon(intn)//definethesimon()function
Simonsaystouchyourtoes"
n<
times."
}//voidfunctionsdon'
tneedreturnstatements
下面试运行情况:
Simonsaystouchyourtoes3times.
512
Simonsaystouchyourtoes512times.
程序中包含了cin语句来从键盘上获取数据。
该程序中包含了除main函数以外的另一个函数simon(),他和main函数定义的格式相同,函数的统一格式如下:
typefunctionname(argumentlist)
statements
注意,定义simon()的代码在main()函数的后面,C++中不允许将函数定义在另一个函数内。
每个函数的定义都是独立的,所有的函数的创建都是平等的。
simon()函数的函数头定义如下:
voidsimon(intn)
以void开头表明simon()没有返回值,因此我们不能类是这样的使用它。
simple=simon(3);
有返回值的函数如下
//convert.cpp--convertsstonetopounds
intstonetolb(int);
//functionprototype
intstone;
Entertheweightinstone:
stone;
intpounds=stonetolb(stone);
stone<
stone="
pounds<
pounds."
intstonetolb(intsts)
return14*sts;
}下面是运行情况:
Entertheweightinsone:
14
14stone=196pounds.
程序通过cin语句给stone提供一个值,然后在main函数中,把这个值传递给stonetolb()函数,这个植被赋给sts之后,stonetolb()用return将14*sts返回给main()。
函数头中的int表明stonetolb()将返回一个整数。
除了int类型之外,C++的内置数据类型还有:
unsignedlong、Iong、unsignedint、unsignedshort、short、char、unsignedchar、signedchar、bool、float、double、longdouble。
对于数据的输入和输出有几道练习题至
二、算法基础
1.什么是算法
算法是完成特定任务的有限指令集。
所有的算法必须满足下面的标准:
a.输入。
由外部题共零个或多个输入量。
b.输出。
至少产生一个输出量。
c.明确性。
每条指令必须清楚,不具模糊性。
d.有限性。
如果跟踪算法的指令,那么对于所有的情况,算法经过有限步以后终止。
e.有效性。
每条指令必须非常基础,原则上使用笔和纸就可以实现
例选择排序
voidSelectionSort(Typea[],intn)
//Sortthearrata[1:
n]intonondecreasingorder.{
for(inti=1;
i<
=n;
i++)
intj=1;
for(intk=i+1;
k<
k++)
if(a[k]<
a[j])j=k;
Typet=a[i];
a[i]=a[j];
a[j]=t;
c1n
c2n
n
c3(ni)
i1
使用该函数时,应将Type替换为C++中的数据类型
3.性能分析
程序P所用时间定义为T(P),T(P)是编译时间和运行时间之和。
下面我们计算一下选择排序运行时所要花费的时间
SelectionSort
cost
times
a[j])
j=k;
a[i]=a[j];
a[j]
c4(ni)
c5ti
c6n
=t;
那么该算法运行的时间
那么,在最坏的条件下,ti的值应该是(ni)
i1
C和n0,使得对于所有的n(nn°
),有f(n)cg(n)。
例
对于所有n1有62nn22n,所以62nn2(2n)。
当然62nn2(n),但是(n)(2n)。
现然无论是O还是Q,都不能精确的描述一个函数
C1,C2和n°
,使得对于所有的n(nn°
),有&
g(n)f(n)c?
g(n)。
对于n2有3n23n且3n24n,所以3n2(n)
©
记号要比O和Q都要精确。
排列生成器©
(n!
)
voidPerm(Typea[],intk,intn)
if(k==n){//Outputpermutation.
for(inti-1;
n;
i++)cout<
a[i]<
else//a[k:
n]hasmorethanonepermutation.//Generatetheserecursively.for(inti=k;
i++){
Typet=a[k];
a[k]=a[i];
a[i]=t;
Perm(a,k+1,n);
//Allpermutationsofa[k+1:
n]t=a[k];
对于下面的程序
#include<
voidPerm(inta[],intk,intn)
if(k<
n-1)
inti,t;
for(i=k;
t=a[k];
a[k]=a[i];
a[i]=t;
Perm(a,k+1,n);
a[i]=t;
inta[3]={1,2,3};
Perm(a,0,3);
该程序的运行结果为
123
132
213
321
312
那么,该函数就完成了对一个数组进行全排列的操作下面,分析该程序,我用圆圈代表每次函数的调用每次函数的调用都用序号表示
1.
a:
123
k:
0
6.
213
2
2.
1
7.
231
3.
8.
321
4.
132
9.
5.
10.
312
排列生成器的另外一个版本
他将输出给定n个布尔变量的所有可能的组合
voidPerm(boola[],intk,intn){
if(k==n)
//statement
}else
a[k]=true;
a[k]=false;
}
在上次冬季赛上有这么一道题竞赛真理
JUNNY在经历了无数次学科竞赛的失败以后,得到了一个真理:
做一题就要对一题!
但是要
完全正确地做对一题是要花很多时间(包括调试时间),而竞赛的时间有限。
所以开始做题之前最好先认真审题,估计一下每一题如果要完全正确地做出来所需要的时间,然后选择一些有把握的题目先做。
当然,如果做完了预先选择的题目之后还有时间,但是这些时间又不足以完全解决一道题目,应该把其他的题目用贪心之类的算法随便做做,争取“骗”一点
分数。
根据每一题解题时间的估计值,确定一种做题方案(即哪些题目认真做,哪些题目“骗”分,哪些不做),使能在限定的时间内获得最高的得分。
INPUTFORMAT:
从标准输入(cin,scanf等)读入数据。
数据有多组,先输入K(K组数据)。
每组第一行有
两个正整数N和T,表示题目的总数以及竞赛的时限(单位秒)。
以下的N行,每行4个正
整数W1i、T1i、W2i、T2i,分别表示第i题:
完全正确做出来的得分,完全正确做出来所花费的时间(单位:
秒),“骗”来的分数,“骗”分所花费的时间(单位秒)。
其中,3<
N<
30,2<
T<
1080000,1wW1i、W2i<
30000,1<
T1i、T2i<
T。
OUTPUTFORMAT:
直接把所求得的最高得分输出。
数据之间需换行。
SAMPLEINPUT:
2
410800
18360031800
224000123000
28600003000
328000246000
37200
50540010900
50720010900
SAMPLEOUTPUT:
50
70
下面我们对问题进行简化。
我们只要考虑是做题还是不做题。
数据只有一组,先输入K(K组数据)。
每组第一行
有两个正整数N和T,表示题目的总数以及竞赛的时限(单位秒)。
以下的N行,每行2个
正整数Wi、Ti,分别表示第i题:
做出来的得分和做出来所花费的时间(单位:
秒),OUTPUT
FORMAT:
直接把所求得的最高得分输出。
510
120
415
score+=t[x][1];
time+=t[x][0];
if(time<
=tSum)
{if(score>
m){m=score;
boola[30];
intn,c;
cin>
n>
tSum;
m=0;
for(c=0;
c<
c++){cin>
t[c][0];
t[c][1];
f(a,0,n);
cout<
m<
work()函数内,然后work函数找到在时间范围内的
就能得到更好的程序cTime){if(k<
n){dfs(k+1,n,cScore,cTime);
dfs(k+1,n,cScore+t[k][1],cTime+t[k][0]);
else
intn,c;
if(cTime<
cin>
m=0;
if(cScore>
m)
for(c=0;
c++)
m=cScore;
dfs(0,n,0,0);
这个程序就是深度优先搜索,如果n非常大,递归调用的次数是非常惊人的,达到2n次。
为了减少递归的次数,我们可以采取剪枝的手段,在递归下一次前判断是否可行。
如果肯定不能就停止递归,节省时间。
m=cScore
intm;
intt[20][2];
inttSum;
voiddfs(intk,intn,intcScore,int
cTime)
if(k<
n)
dfs(k+1,n,cScore,cTime);
tSum)
dfs(k+1,n,cScore+
t[k][1],cTime+t[k][0]);
为了达到更好的剪枝效果,可以在搜索前对数据进行排序。
竞赛真理原题也可用这种思想去解。
更复杂的算法将在以后进行讲解.