要考试了,做几个简单题复习一下数据结构。
栈的应用:http://noi.openjudge.cn/ch0303/1696/
(注意题目描叙是有问题的,应该是波兰表达式)
1696:逆波兰表达式
- 总时间限制:
- 1000ms
- 内存限制:
- 65536kB
- 描述
- 逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的逆波兰表示法为+ 2 3。逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 + 3) * 4的逆波兰表示法为* + 2 3 4。本题求解逆波兰表达式的值,其中运算符包括+ - * /四个。
- 输入
- 输入为一行,其中运算符和运算数之间都用空格分隔,运算数是浮点数。
- 输出
- 输出为一行,表达式的值。
可直接用printf("%f ", v)输出表达式的值v。 - 样例输入
-
* + 11.0 12.0 + 24.0 35.0
- 样例输出
-
1357.000000
- 提示
- 可使用atof(str)把字符串转换为一个double类型的浮点数。atof定义在math.h中。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 stack<string> str; 5 stack<double> num; 6 vector<string> v; 7 string s; 8 9 int main() 10 { 11 while(cin>>s) { 12 v.push_back(s); 13 getchar(); 14 } 15 16 for(int i=v.size()-1;i>=0;i--) { 17 if(v[i][0]=='+') 18 { 19 double num1 = num.top(); 20 num.pop(); 21 double num2 = num.top(); 22 num.pop(); 23 num.push(num1+num2); 24 } 25 else if(v[i][0]=='-') { 26 double num1 = num.top(); 27 num.pop(); 28 double num2 = num.top(); 29 num.pop(); 30 31 num.push(num1-num2); 32 33 } 34 else if(v[i][0]=='*') { 35 double num1 = num.top(); 36 num.pop(); 37 double num2 = num.top(); 38 num.pop(); 39 num.push(num1*num2); 40 } 41 else if(v[i][0]=='/') { 42 double num1 = num.top(); 43 num.pop(); 44 double num2 = num.top(); 45 num.pop(); 46 47 num.push(num1/num2); 48 } 49 else { 50 double x = atof(v[i].c_str()); 51 num.push(x); 52 } 53 } 54 55 printf("%.6lf ",num.top()); 56 return 0; 57 }
队列的应用:http://noi.openjudge.cn/ch0304/2729/
2729:Blah数集
- 总时间限制:
- 3000ms
- 内存限制:
- 65536kB
- 描述
- 大数学家高斯小时候偶然间发现一种有趣的自然数集合Blah,对于以a为基的集合Ba定义如下:
(1) a是集合Ba的基,且a是Ba的第一个元素;
(2)如果x在集合Ba中,则2x+1和3x+1也都在集合Ba中;
(3)没有其他元素在集合Ba中了。
现在小高斯想知道如果将集合Ba中元素按照升序排列,第N个元素会是多少? - 输入
- 输入包括很多行,每行输入包括两个数字,集合的基a(1<=a<=50))以及所求元素序号n(1<=n<=1000000)
- 输出
- 对于每个输入,输出集合Ba的第n个元素值
- 样例输入
-
1 100 28 5437
- 样例输出
-
418 900585
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 long long a,n; 7 while(scanf("%lld%lld",&a,&n)!=EOF) 8 { 9 10 queue<long long> small; 11 queue<long long> big; 12 13 long long x = a; 14 15 small.push(a*2+1); 16 big.push(a*3+1); 17 for(int i=1; i<n; i++) 18 { 19 if(small.front()<big.front()) 20 { 21 x = small.front(); 22 small.pop(); 23 small.push(x*2+1); 24 big.push(x*3+1); 25 } 26 27 else if(small.front()>big.front()) 28 { 29 x = big.front(); 30 big.pop(); 31 big.push(x*3+1); 32 small.push(x*2+1); 33 } 34 35 else 36 { 37 x = small.front(); 38 small.pop(); 39 big.pop(); 40 big.push(x*3+1); 41 small.push(x*2+1); 42 } 43 } 44 45 printf("%lld ",x); 46 } 47 48 return 0; 49 }
hash:http://noi.openjudge.cn/ch0305/1551/
1551:Sumsets
- 总时间限制:
- 1000ms
- 内存限制:
- 65536kB
- 描述
- Given S, a set of integers, find the largest d such that a + b + c = d where a, b, c, and d are distinct elements of S.
- 输入
- Several S, each consisting of a line containing an integer 1 <= n <= 1000 indicating the number of elements in S, followed by the elements of S, one per line. Each element of S is a distinct integer between -536870912 and +536870911 inclusive. The last line of input contains 0.
- 输出
- For each S, a single line containing d, or a single line containing "no solution".
- 样例输入
-
5 2 3 5 7 12 5 2 16 64 256 1024 0
- 样例输出
-
12 no solution
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 int n; 6 long long a[1010]; 7 8 struct Point 9 { 10 int i,j; 11 }; 12 13 int main() 14 { 15 while(scanf("%d",&n),n) 16 { 17 18 for(int i=0; i<n; i++) 19 scanf("%lld",&a[i]); 20 21 sort(a,a+n); 22 23 map<long long,Point> maps; 24 for(int i=0; i<n; i++) 25 { 26 for(int j=i+1; j<n; j++) 27 { 28 int sum = a[i]+a[j]; 29 maps[sum] = {i,j}; 30 } 31 } 32 33 long long ans = -1; 34 bool flag = false; 35 for(int i=0; i<n; i++) 36 { 37 for(int j=0; j<n&&j!=i; j++) 38 { 39 if(maps.count(a[i]-a[j])&&maps[a[i]-a[j]].i!=i&&maps[a[i]-a[j]].j!=j&&maps[a[i]-a[j]].i!=j&&maps[a[i]-a[j]].j!=i) 40 { 41 ans = max(ans,a[i]); 42 flag = true; 43 } 44 } 45 } 46 47 if(flag) 48 printf("%lld ",ans); 49 else 50 puts("no solution"); 51 52 } 53 54 return 0; 55 }
二叉树:http://noi.openjudge.cn/ch0306/1758/
1758:二叉树
- 总时间限制:
- 1000ms
- 内存限制:
- 65536kB
- 描述
如上图所示,由正整数1, 2, 3, ...组成了一棵无限大的二叉树。从某一个结点到根结点(编号是1的结点)都有一条唯一的路径,比如从10到根结点的路径是(10, 5, 2, 1),从4到根结点的路径是(4, 2, 1),从根结点1到根结点的路径上只包含一个结点1,因此路径就是(1)。对于两个结点x和y,假设他们到根结点的路径分别是(x1, x2, ... ,1)和(y1, y2, ... ,1)(这里显然有x = x1,y = y1),那么必然存在两个正整数i和j,使得从xi 和 yj开始,有xi = yj , xi + 1 = yj + 1, xi + 2 = yj + 2,... 现在的问题就是,给定x和y,要求xi(也就是yj)。- 输入
- 输入只有一行,包括两个正整数x和y,这两个正整数都不大于1000。
- 输出
- 输出只有一个正整数xi。
- 样例输入
-
10 4
- 样例输出
-
2
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 1000+10; 6 7 bool vis[maxn]; 8 9 int main() 10 { 11 int x,y; 12 scanf("%d%d",&x,&y); 13 while(1) { 14 vis[x] = 1; 15 if(x==1) 16 break; 17 else x/=2; 18 } 19 20 while(1) { 21 if(vis[y]) 22 break; 23 else y/=2; 24 } 25 26 printf("%d ",y); 27 28 return 0; 29 }
最小生成树:http://noi.openjudge.cn/ch0403/253/
同POJ1251
http://www.cnblogs.com/TreeDream/p/5728160.html
253:丛林中的路
- 总时间限制:
- 1000ms
- 内存限制:
- 65536kB
- 描述
热带岛屿Lagrishan的首领现在面临一个问题:几年前,一批外援资金被用于维护村落之间的道路,但日益繁茂的丛林无情的侵蚀着村民的道路,导致道路维修开销巨大,长老会不得不放弃部分道路的维护。上图左侧图显示的是正在使用道路的简图以及每条路每个月的维修费用(单位为aacms)。现在长老会需要提出一种方案,即需要保证村落之间都可以互相到达,又要将每个月的道路维修费用控制在最小。村子编号为从A到I。上图右侧显示的方案最小维修开销为216 aacms每月。
- 输入
- 输入包含1~100个数据集,最后一行为0.每个数据集第一行为村落数目n, 1 < n < 27,依次用字母表的前n个字母标记。接下来有n-1行,每行的第一个数据便是按字母顺序排列的村子编号(不包括最后一个村庄)。每个村庄后面的数据k代表该村庄通往编号在其之后的村庄的道路数目,如A 2 B 12 I 25,代表A村庄有2个编号在A之后的村庄和其相连。若k大于0,k后面会依次给出这k个村庄的编号以及各自到起始村庄的道路维修费用,如A 2 B 12 I 25,代表A和B之间道路维修费用为12, A和I之间道路维修费用为25(维修费用为不超过100的正整数).路的总数目不超过75条,每个村庄到其他村庄不会有超过15条路(包括编号在其之前和之后的)。
- 输出
- 每个数据集有一个输出:针对解决方案每个月维修道路的小费用。
提示:蛮力算法虽能找出解决方案,但将会超出时间限制。 - 样例输入
-
9 A 2 B 12 I 25 B 3 C 10 H 40 I 8 C 2 D 18 G 55 D 1 E 44 E 2 F 60 G 38 F 0 G 1 H 35 H 1 I 35 3 A 2 B 10 C 40 B 1 C 20 0
- 样例输出
-
216 30