May 7, 2008

STL的头文件中描述了一个看上去非常简单的模板类pair,用来表示一个二元组或元素对,并提供了按照字典序对元素对进行大小比较的比较运算符模板函数。

例如,想要定义一个对象表示一个平面坐标点,则可以:

pair p1;
cin >> p1.first >> p1.second;

pair模板类需要两个参数:首元素的数据类型和尾元素的数据类型。pair模板类对象有两个成员:first和second,分别表示首元素和尾元素。

中已经定义了pair上的六个比较运算符:<、>、<=、>=、==、!=,其规则是先比较first,first相等时再比较second,这符合大多数应用的逻辑。当然,也可以通过重载这几个运算符来重新指定自己的比较逻辑。

除了直接定义一个pair对象外,如果需要即时生成一个pair对象,也可以调用在中定义的一个模板函数:make_pair。make_pair需要两个参数,分别为元素对的首元素和尾元素。

在题1067--Ugly Numbers中,就可以用pair来表示推演树上的结点,用first表示结点的值,用second表示结点是由父结点乘以哪一个因子得到的。

#include
#include

using namespace std;

typedef pair node_type;

main()
{
unsigned long result[1500];
priority_queue< node_type, vector, greater > Q;
Q.push( make_pair(1, 2) );
for (int i=0; i<1500; i++)
{
node_type node = Q.top(); Q.pop();
switch(node.second)
{
case 2: Q.push( make_pair(node.first*2, 2) );
case 3: Q.push( make_pair(node.first*3, 3) );
case 5: Q.push( make_pair(node.first*5, 5) );
}
result[i] = node.first;
}

int n;
cin >> n;
while (n>0)
{
cout << result[n-1] << endl;
cin >> n;
}

return 1;
}

看上去是很简单的一个头文件,但是的设计中却浓缩反映了STL设计的基本思想。有意深入了解和研究STL的同学,仔细阅读和体会这个简单的头文件,不失为一种入门的途径。

一、关于STL

STL(Standard Template Library,标准模板库)是C++语言标准中的重要组成部分。STL以模板类和模板函数的形式为程序员提供了各种数据结构和算法的精巧实现,程序员如果能够充分地利用STL,可以在代码空间、执行时间和编码效率上获得极大的好处。
STL大致可以分为三大类:算法(algorithm)、容器(container)、迭代器(iterator)。

STL容器是一些模板类,提供了多种组织数据的常用方法,例如vector(向量,类似于数组)、list(列表,类似于链表)、deque(双向队列)、set(集合)、map(映象)、stack(栈)、queue(队列)、priority_queue(优先队列)等,通过模板的参数我们可以指定容器中的元素类型。

STL算法是一些模板函数,提供了相当多的有用算法和操作,从简单如for_each(遍历)到复杂如stable_sort(稳定排序)。

STL迭代器是对C中的指针的一般化,用来将算法和容器联系起来。几乎所有的STL算法都是通过迭代器来存取元素序列进行工作的,而STL中的每一个容器也都定义了其本身所专有的迭代器,用以存取容器中的元素。有趣的是,普通的指针也可以像迭代器一样工作。

熟悉了STL后,你会发现,很多功能只需要用短短的几行就可以实现了。通过STL,我们可以构造出优雅而且高效的代码,甚至比你自己手工实现的代码效果还要好。

STL的另外一个特点是,它是以源码方式免费提供的,程序员不仅可以自由地使用这些代码,也可以学习其源码,甚至按照自己的需要去修改它。

下面是用STL写的题1067--Ugly Numbers的代码:

#include <iostream>
#include <queue>

using namespace std;

typedef pair<unsigned long, int> node_type;

main()
{
 unsigned long result[1500];
 priority_queue< node_type, vector<node_type>, greater<node_type> > Q;
 Q.push( make_pair(1, 2) );
 for (int i=0; i<1500; i++)
 {
  node_type node = Q.top(); Q.pop();
  switch(node.second)
  {
  case 2: Q.push( make_pair(node.first*2, 2) );
  case 3: Q.push( make_pair(node.first*3, 3) );
  case 5: Q.push( make_pair(node.first*5, 5) );
  }
  result[i] = node.first;
 }

 int n;
 cin >> n;
 while (n>0)
 {
  cout << result[n-1] << endl;
  cin >> n;
 }

 return 1;
}



二、使用STL

在C++标准中,STL被组织为以下的一组头文件(注意,是没有.h后缀的!):

algorithm / deque / functional / iterator / list / map

memory / numeric / queue / set / stack / utility / vector

当我们需要使用STL的某个功能时,需要嵌入相应的头文件。但要注意的是,在C++标准中,STL是被定义在std命名空间中的。如下例所示:

#include <stack>

main()

{

std::stack<int> s;

s.push(0);

...

return 1;

}

如果希望在程序中直接引用STL,也可以在嵌入头文件后,用using namespace语句将std命名空间导入。如下例所示:

#include <stack>

using namespace std;

main()

{

stack<int> s;

s.push(0);

...

return 1;

}

STL是C++语言机制运用的一个典范,通过学习STL可以更深刻地理解C++语言的思想和方法。在本系列的文章中不打算对STL做深入的剖析,而只是想介绍一些STL的基本应用。

在ACM竞赛中,熟练掌握和运用STL对快速编写实现代码会有极大的帮助。

一、ACM/ICPC竞赛的特点

ACM/ICPC(国际大学生程序设计竞赛)是以算法设计为主的程序设计竞赛,并不涉及具体的应用技术。

ACM/ICPC竞赛以组队形式参赛,每个参赛队由三名队员组成,共同使用一台计算机解题。通常每场比赛的试题为6至10题,根据各队的完成题数和罚时进行排名。题目提交通过称为完成,从比赛开始到提交成功所用的时间为题目的基础罚时,另外,一道题目每提交失败一次,将增加20分钟罚时。也就是说,参赛队要尽可能用最快的速度、最少的失败次数,解决最多的题目。

二、输入和输出处理
试题一般采用标准输入和输出方式读取输入和产生输出,在题目中会详细描述输入和输出的格式和值域范围,所写的程序一定要严格遵守题目指定的输入输出格式。

在比赛试题的输入和输出处理上,针对一些常见的情形,有一些常用的方法。

1、多测试用例的输入和输出

有些试题在一次输入中只包含一个测试用例,也就是说,程序每运行一次,只算一道题。也有些试题在一次输入中包含多个测试用例,也就是说,程序每运行一次,要计算多道题。

对多用例输入,通常会先输入要计算的用例的个数,然后依次输入每个测试用例的输入数据,但程序并不需要等到所有的测试用例都计算完后再输出所有测试用例的计算结果,而是可以读入一个测试用例,输出一个结果,再读入一个测试用例,再输出一个结果。因此对多用例输入的试题,可以用这样的输入模式:

以C++为例:

int n;

cin >> n;

for (int i=0; i

{

读入测试用例数据

计算

输出计算结果

}

2、单测试用例输入的结束判断
对单用例输入,最主要的问题是如何知道输入什么时候结束。

有些试题会指定某种特殊的输入值作为输入的结束标志,这种情况比较容易处理,只须在读入后,判断一下读入的内容是否为约定结束值即可。

有些试题并不指定特殊的输入值,而是以EOF(文件结束标志)作为结束标志。如果从文件流读入,当读到文件尾时,输入返回EOF。如果从键盘读入时,在Windows的终端中,是以Ctrl+Z表示EOF。对于这种情况,可以用这样的输入模式:

以C++为例:

int m, n; // 假设要连续输入一组整数对

while (cin>>m>>n)

{

处理整数对(m, n)

}

以C语言为例:

int m, n;

while (scanf("%d%d", &m, &n)==2)

{

处理整数对(m, n)

}

三、数据结构的设计
很多试题中已经给出了数据量的上限,因此可以很方便地以数组的方式定义数据结构。但也要注意到有些题目中没有明确指出数据上限时,切不可盲目定义数组大小。

例如在题1070(多项式求和)中,并未说明输入多项式的项数,对这种情况就不宜用数组方式来表示多项式了——除非你的运气足够好,所开辟的数组大小能够经受所有的测试用例的考验。

除了使用一般的数组或链表结构外,对使用C++的选手来说,STL也是一大利器,充分运用可以有效提高编程的效率和正确性。

四、测试用例的考虑
在试题中通常会给出测试用例的样例,这通常会被我们用来测试自己的程序,而且很多选手往往在正确计算出测试用例样例时,会认为自己的程序是正确的。

其实测试用例的样例只是测试用例的个例,实际用于测试的测试用例往往会涵盖各种极限情况和边界情况,而且有时测试用例的数量还会比较大,甚至会重复测试同一个测试用例。因此我们的程序能够通过样例测试,未必能够通过所有的测试用例的测试,一方面要全面考虑所有可能的极限情况和边界情况,一方面程序要有足够的效率。

April 5, 2008

有一根27厘米的细木杆,在第3厘米、7厘米、11厘米、17厘米、23厘米这五个位置上各有一只蚂蚁。 木杆很细,不能同时通过一只蚂蚁。开始 时,蚂蚁的头朝左还是朝右是任意的,它们只会朝前走或调头,但不会后退。当任意两只蚂蚁碰头时,两只蚂蚁会同时调头朝反方向走。假设蚂蚁们每秒钟可以走一厘米的距离。 编写程序,求所有蚂蚁都离开木杆的最小时间和最大时间。

----------------------------------------------------


***  最笨的方法当然是把蚂蚁看成一个一个的去遍历左右; // 还真有人这么写

***  然后好一点的方法是递归:

类似这种:http://blog.csdn.net/andylin02/archive/2007/07/27/1711701.aspx
就不贴代码了

***  最简单的方法当时是“禅”啦

Python代码:
def f(x):return 27-x
a=[3,7,11,17,23] 
b=map(f,a)
print 'max:',max(max(a),max(b))
print 'min:',max(min(a[x],b[x]) for x in range(0,5))


那你看,万生在人海穿梭,相遇又回头:如果把这个过程想象成我继续走,他继续走;
我穿着他的躯壳,他穿着我的躯壳,那岂不等同于我们没有相识

所以
要算最长的的时间 就是初始状况下 蚂蚁离距离它最远的那个边的最大值。
要算最少的时间 就是所有蚂蚁中最后一只走出来的时间,就是每个蚂蚁都朝着离自己近的一个端点爬,然后这些时间中最大的一个。
上面是一段简单的草稿代码 就么的注释了。

缘分那。。缘分。。

March 26, 2008

关键词(Tag): c++ stl soa clémentine projects

Tags: ,,,.
November 16, 2006

 

Problem Description:We dont want to interview all the candidates in order to get the best one also do not wish ti hire and fire as we find better applicants.Instead we are willing to settle for a candidate who is close to the best.In this problem we must obey one company requirement:after each interview we must either immediately offer the position to the applicant or must tell them they will not get the job.what is the trade-off between minimizing the amount of interviewing and maximizing the quality of the candidate hired?

On-Line-Hiring-Max(k,n)
bestscore <-- ---inf
for i <--1 to  k
      do if score(i)>bestscore
                       then bestscore <----score(i)
for i <--k+1 to n
      do if score(i)>bestscore 
                            then return i
return n

we wish to determine for each possible value of k, the probability that we hire the most qualified applicant.
Let Si be the event that we succeed in choosing the best-qualified applicant in the ith one interviewed.
Pr(s)=sigma(i=k+1,n){Si} PR(Si)=k/(n(i-1)) 
=k/n*sigma(i=k,n-1)1/i Pr(s)>=1/e           say lnk=lnn-1,Max.

This is a much easier way than Nju_Mcm_Training_Professor Yao's method.

appended question.  How we can get the best expect applicant? The average expect rank?