写在前面
1.2018期末机考题目网址:
(1)普通班:http://dsa.openjudge.cn/final20181223
(2)实验班:http://dsa.openjudge.cn/final2018ht
2.2018期末机考模拟测试:
http://dsa.openjudge.cn/2018ftest/
3.参考资料下载地址
(1)http://media.openjudge.cn/upload/DSMooc/DSCode_ZhangWangZhao2008_06.rar
(2)http://media.openjudge.cn/upload/DSMooc/DScodeCversion.rar (C语言代码包)
(3)http://media.openjudge.cn/upload/DSMooc/201810cplusplus.zip (C++手册)
(4)http://media.openjudge.cn/upload/DSMooc/DSAlgoWeissMark.pdf (英文教材)
1.词典
其他网址:http://bailian.openjudge.cn/practice/2804/
题目
- 总时间限制:
- 3000ms
- 内存限制:
- 65536kB
- 描述
-
你旅游到了一个国外的城市。那里的人们说的外国语言你不能理解。不过幸运的是,你有一本词典可以帮助你。
- 输入
- 首先输入一个词典,词典中包含不超过100000个词条,每个词条占据一行。每一个词条包括一个英文单词和一个外语单词,两个单词之间用一个空格隔开。而且在词典中不会有某个外语单词出现超过两次。词典之后是一个空行,然后给出一个由外语单词组成的文档,文档不超过100000行,而且每行只包括一个外语单词。输入中出现单词只包括小写字母,而且长度不会超过10。
- 输出
- 在输出中,你需要把输入文档翻译成英文,每行输出一个英文单词。如果某个外语单词不在词典中,就把这个单词翻译成“eh”。
- 样例输入
-
dog ogday cat atcay pig igpay froot ootfray loops oopslay atcay ittenkay oopslay
- 样例输出
-
cat eh loops
- 提示
- 输入比较大,推荐使用C语言的I / O函数。
- 来源
翻译自Waterloo local 2001.09.22的试题
我的代码
1 # include <iostream>
2 # include <cstdio>
3 # include <algorithm>
4 # include <string.h>
5 using namespace std;
6
7 //type: DIC
8 typedef struct{
9 char w1[12], w2[12];
10 } DIC;
11
12 //d1.w1 < d2.w1
13 bool cmp(DIC d1, DIC d2){
14 return (strcmp(d1.w2, d2.w2) < 0);
15 }
16
17
18 DIC d[100010]; //dictionary: increasing order
19 int n = 0; //n pairs of words in dic
20 char s[25]; //input strings s[]
21
22 //initialize dictionary: separate 2 words
23 void IniDic(int num){
24 int pos;
25 for(pos = 0; s[pos] != ' '; ++pos);
26 strncpy(d[num].w1, s, pos);
27 strncpy(d[num].w2, s+pos+1, 11);
28 }
29
30 //binary search: lookfor word s[]
31 void SearchWord(){
32 int r = 0, l = n - 1, m, t; //first, last, middle
33 while(r < l){
34 m = (r + l) / 2;
35 if((t = strcmp(s, d[m].w2)) == 0){
36 printf("%s
", d[m].w1);
37 return; //find s = d[m].w1
38 }
39 else if(t > 0) //s > d[m].w1
40 r = m + 1;
41 else //s < d[m].w1
42 l = m - 1;
43 }
44 if(strcmp(s, d[r].w2) == 0)
45 printf("%s
", d[r].w1);
46 else
47 printf("eh
");
48 return;
49 }
50
51 int main(){
52 while((s[0] = cin.get()) != '
'){
53 cin.getline(s+1, 24);
54 IniDic(n++);
55 }
56 //cout << n << endl;
57 sort(d, d+n, cmp); //sort dictionary
58 //for(int i = 0; i < n; ++i)
59 //printf("dic[%d]: %s %s
", i, d[i].w1, d[i].w2);
60 while(cin >> s){
61 SearchWord();
62 }
63 return 0;
64 }
tips
1.空行的识别,get(),cin.getline()等
2.单词排序:定义比较函数<template T> bool cmp(T t1, T t2);
3.单词查找:二分查找
2.Field Reduction
来源:USACO 2016 US Open contest
题目
- 总时间限制:
- 10000ms
- 单个测试点时间限制:
- 1000ms
- 内存限制:
- 65536kB
- 描述
-
Farmer John's N cows (5≤N≤50,000) are all located at distinct positions in his two-dimensional field. FJ wants to enclose all of the cows with a rectangular fence whose sides are parallel to the x and y axes, and he wants this fence to be as small as possible so that it contains every cow (cows on the boundary are allowed). FJ is unfortunately on a tight budget due to low milk production last quarter. He would therefore like to build an even smaller fenced enclosure if possible, and he is willing to sell up to three cows from his herd to make this possible. Please help FJ compute the smallest possible area he can enclose with his fence after removing up to three cows from his herd (and thereafter building the tightest enclosing fence for the remaining cows). For this problem, please treat cows as points and the fence as a collection of four line segments (i.e., don't think of the cows as "unit squares"). Note that the answer can be zero, for example if all remaining cows end up standing in a common vertical or horizontal line.
农夫约翰的N(5<=N<=50000)头牛被定在了平面内的不同的位置。他想用栅栏(平行于x和y轴)围住所有的牛。他想这个栅栏尽可能小(牛在边界上也被视作围住)。
他因为牛奶产量低而感到经费紧张,所以他想卖掉三头牛再围起剩下的牛。请算出栅栏围出的最小面积。(面积有可能为0,例如,最后剩下的牛排成一排或一列。)
- 输入
- The first line of input contains N. The next N lines each contain two integers specifying the location of a cow. Cow locations are positive integers in the range 1…40,000.
第一行输入正整数n
剩下2-n+1行,输入每头牛的坐标位置(x,y) ( 1<= x,y<=40000的整数)
- 输出
- Write a single integer specifying the minimum area FJ can enclose with his fence after removing up to three carefully-chosen cows from his herd.
- 最小面积
- 样例输入
-
6 1 1 7 8 10 9 8 12 4 100 50 7
- 样例输出
-
12
思路
按x、y的大小分别排序,每次去掉xmin/xmax/ymin/ymax的一头牛,dfs或者直接枚举
我的代码
(只在本地测试了一些数据)
版本一:
1 # include <iostream>
2 # include <algorithm>
3 using namespace std;
4 #define MAXSPACE 2000000000
5
6 //cow's position
7 typedef struct{
8 int x, y;
9 } COW;
10
11 //compare cow's x
12 bool cmpx(COW c1, COW c2){
13 return c1.x < c2.x;
14 }
15
16 //compare cow's y
17 bool cmpy(COW c1, COW c2){
18 return c1.y < c2.y;
19 }
20
21 int n;
22 COW * c;
23
24 //find min from 4 values
25 int MyMin(int a, int b, int c, int d){
26 if(a < b){
27 if(a < c){
28 if(a < d) return a;
29 else return d;
30 }
31 else{
32 if(c < d) return c;
33 else return d;
34 }
35 }
36 else{
37 if(b < c){
38 if(b < d) return b;
39 else return d;
40 }
41 else{
42 if(c < d) return c;
43 else return d;
44 }
45 }
46 }
47
48 //calculate min space needed after selling r cows from c[s~e-1]
49 int MinSpace(int s, int e, int r){
50 if(r == 0){ //no cows to sell
51 int x1, x2, y1, y2;
52 sort(c+s, c+e, cmpx);
53 x1 = c[s].x;
54 x2 = c[e-1].x;
55 sort(c+s, c+e, cmpy);
56 y1 = c[s].y;
57 y2 = c[e-1].y;
58 return (x2-x1)*(y2-y1);
59 }
60 int mx1 = MAXSPACE, mx2 = MAXSPACE, my1 = MAXSPACE, my2 = MAXSPACE;
61 sort(c+s, c+e, cmpx);
62 //sell the cow with min-x
63 //if c[s].x == c[s+3].x, then selling cow s won't make space smaller (from x's perspective)
64 if(s+3 < e && c[s].x != c[s+3].x)
65 mx1 = MinSpace(s+1, e, r-1);
66 //sell the cow with max-x
67 if(s+3 < e && c[e-4].x != c[e-1].x)
68 mx2 = MinSpace(s, e-1, r-1);
69 sort(c+s, c+e, cmpy);
70 //sell the cow with min-y
71 if(s+3 < e && c[s].y != c[s+3].y)
72 my1 = MinSpace(s+1, e, r-1);
73 //sell the cow with max-y
74 if(s+3 < e && c[e-4].y != c[e-1].y)
75 my2 = MinSpace(s, e-1, r-1);
76 return MyMin(mx1, mx2, my1, my2);
77 }
78
79 int main(){
80 cin >> n;
81 c = new COW[n+1];
82 for(int i = 0; i < n; ++i)
83 cin >> c[i].x >> c[i].y;
84 cout << MinSpace(0, n, 3) << endl;
85 delete [] c;
86 return 0;
87 }
有很多重复的sort,非常耗时
版本二:
1 # include <iostream>
2 # include <algorithm>
3 # include <cstdio>
4 using namespace std;
5 #define MAXSPACE 2000000000
6
7 //cow's position
8 typedef struct{
9 int x, y;
10 } COW;
11
12 //compare cow's x
13 bool cmpx(COW c1, COW c2){
14 return c1.x < c2.x;
15 }
16
17 //compare cow's y
18 bool cmpy(COW c1, COW c2){
19 return c1.y < c2.y;
20 }
21
22 int n, ans = MAXSPACE;
23 COW * c;
24
25 //min value of a & b
26 int MyMin(int a, int b){
27 if(a < b) return a;
28 else return b;
29 }
30
31 //calculate space needed
32 //after selling x1 cows with min-x, x2 cows with max-x,
33 //and selling y1 cows with min-y, y2 cows with max-y
34 void Space(int x1, int x2, int y1, int y2){
35 sort(c, c+n, cmpx);
36 sort(c+x1, c+n-x2, cmpy);
37 int miny = c[x1+y1].y, maxy = c[n-x2-y2-1].y;
38 sort(c+x1+y1, c+n-x2-y2, cmpx);
39 int minx = c[x1+y1].x, maxx = c[n-x2-y2-1].x;
40 int s = (maxx - minx) * (maxy - miny);
41 /* testing code */
42 /*
43 printf("%d %d %d %d %d
", x1,x2,y1,y2, s);
44 printf(" x: %d-%d, y: %d-%d
", minx,maxx, miny, maxy);
45 for(int i=0; i<n; ++i)
46 printf("(%d,%d) ", c[i].x, c[i].y);
47 printf("
");
48 */
49 ans = MyMin(s, ans);
50 }
51
52 int main(){
53 cin >> n;
54 c = new COW[n+1];
55 for(int i = 0; i < n; ++i)
56 cin >> c[i].x >> c[i].y;
57 for(int i = 0; i <= 3; ++i)
58 for(int j = 0; i+j <= 3; ++j)
59 for(int k = 0; i+j+k <= 3; ++k)
60 Space(i, j, k, 3-i-j-k);
61 cout << ans << endl;
62 delete [] c;
63 return 0;
64 }
枚举要去掉的牛的位置和个数
3.Ultra-QuickSort
其他网址:http://bailian.openjudge.cn/practice/2299/
题目
- 总时间限制:
- 7000ms
- 内存限制:
- 65536kB
- 描述
- In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence
9 1 0 5 4 ,
Ultra-QuickSort produces the output0 1 4 5 9 .
Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence. - 输入
- The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.
- 输出
- For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.
- 样例输入
-
5 9 1 0 5 4 3 1 2 3 0
- 样例输出
-
6 0
- 来源
- Waterloo local 2005.02.05
我的代码
1 # include <cstdio>
2 using namespace std;
3
4 int main(){
5 int n, a[500000], cnt, tmp;
6 scanf("%d", &n);
7 while(n){
8 cnt = 0;
9 for(int i = 0; i < n; ++i)
10 scanf("%d", a + i);
11 for(int i = n - 1; i; --i)
12 for(int j = 0; j < i; ++j){
13 if(a[j] > a[j+1]){
14 tmp = a[j];
15 a[j] = a[j+1];
16 a[j+1] = tmp;
17 ++cnt;
18 }
19 }
20 printf("%d
", cnt);
21 scanf("%d", &n);
22 }
23 return 0;
24 }
1 # include <cstdio>
2 using namespace std;
3
4 int main(){
5 int n, a[500000], cnt, tmp;
6 bool f; //flag
7 scanf("%d", &n);
8 while(n){
9 cnt = 0;
10 for(int i = 0; i < n; ++i)
11 scanf("%d", a + i);
12 for(int i = n - 1; i; --i){
13 f = 1; //flag
14 for(int j = 0; j < i; ++j){
15 if(a[j] > a[j+1]){
16 tmp = a[j];
17 a[j] = a[j+1];
18 a[j+1] = tmp;
19 ++cnt;
20 f = 0; //flag
21 }
22 }
23 if(f) break;
24 }
25 printf("%d
", cnt);
26 scanf("%d", &n);
27 }
28 return 0;
29 }
冒泡(复杂度O(n^2))妥妥TLE
换了归并(复杂度O(nlgn)),终于AC
1 # include <cstdio>
2 using namespace std;
3
4 //length n, array a[], temp array t[]
5 int n, a[500000], t[500000];
6
7 //Merge(start, middle, end)
8 long long Merge(int s, int m, int e){
9 int i = s, j = m+1, k = s;
10 long long cnt = 0;
11 while(i <= m && j <= e){
12 if(a[i] < a[j])
13 t[k++] = a[i++];
14 else{
15 t[k++] = a[j++];
16 cnt += j - k; //a[j] go to a[k] needs j-k exchanges
17 }
18 }
19 while(i <= m) t[k++] = a[i++];
20 while(j <= e) t[k++] = a[j++];
21 for(int l = s; l <= e; ++l)
22 a[l] = t[l];
23 return cnt;
24 }
25
26 //Divide & sort & merge
27 long long MergeSort(int s, int e){
28 if(s >= e) return 0; //exit of recursion
29 int m = (s + e) / 2;
30 long long ret = 0;
31 ret += MergeSort(s, m); //sort a[s~m]
32 ret += MergeSort(m + 1, e); //sort a[m+1~e]
33 ret += Merge(s, m, e); //merge a[s~m] & a[m+1~e]
34 return ret;
35 }
36
37 int main(){
38 scanf("%d", &n);
39 while(n){
40 for(int i = 0; i < n; ++i)
41 scanf("%d", a + i);
42 printf("%lld
", MergeSort(0, n-1));
43 scanf("%d", &n);
44 }
45 return 0;
46 }
tips:
1.注意数据类型用long long (亲测int会WA)
2.采用归并排序,记录归并过程中记录交换次数(AC代码第16行:cnt += j-k 或 cnt += m-i+1)
4.表达式·表达式树·表达式求值
其他网址:http://dsa.openjudge.cn/tree/0609/
题目
- 总时间限制:
- 1000ms
- 内存限制:
- 65535kB
- 描述
-
众所周知,任何一个表达式,都可以用一棵表达式树来表示。例如,表达式a+b*c,可以表示为如下的表达式树:
+
/
a *
/
b c现在,给你一个中缀表达式,这个中缀表达式用变量来表示(不含数字),请你将这个中缀表达式用表达式二叉树的形式输出出来。
- 输入
- 输入分为三个部分。
第一部分为一行,即中缀表达式(长度不大于50)。中缀表达式可能含有小写字母代表变量(a-z),也可能含有运算符(+、-、*、/、小括号),不含有数字,也不含有空格。
第二部分为一个整数n(n < 10),表示中缀表达式的变量数。
第三部分有n行,每行格式为C x,C为变量的字符,x为该变量的值。 - 输出
- 输出分为三个部分,第一个部分为该表达式的逆波兰式,即该表达式树的后根遍历结果。占一行。
第二部分为表达式树的显示,如样例输出所示。如果该二叉树是一棵满二叉树,则最底部的叶子结点,分别占据横坐标的第1、3、5、7……个位置(最左边的坐标是1),然后它们的父结点的横坐标,在两个子结点的中间。如果不是满二叉树,则没有结点的地方,用空格填充(但请略去所有的行末空格)。每一行父结点与子结点中隔开一行,用斜杠(/)与反斜杠()来表示树的关系。/出现的横坐标位置为父结点的横坐标偏左一格,出现的横坐标位置为父结点的横坐标偏右一格。也就是说,如果树高为m,则输出就有2m-1行。
第三部分为一个整数,表示将值代入变量之后,该中缀表达式的值。需要注意的一点是,除法代表整除运算,即舍弃小数点后的部分。同时,测试数据保证不会出现除以0的现象。 - 样例输入
-
a+b*c 3 a 2 b 7 c 5
- 样例输出
-
abc*+ + / a * / b c 37
我的代码
1 # include <iostream>
2 # include <cstdio>
3 # include <stack>
4 using namespace std;
5
6 char a[20], b[20], c; //input a[], answer b[]
7 char ** pic; //picture of tree
8 int v[30], n, t;//v[] store values
9 int len; //len = lenght of b[]
10 int pos; //current index when biulding tree
11 int dep = 0; //depth of tree
12 stack<int> st1; //help calculate
13
14 //define Node of binary tree
15 typedef struct NODE{
16 char c; //symbol of node
17 int d; //depth of node
18 NODE *l, *r;//pointer to children
19 } Node;
20
21 Node * root, * cur;
22
23 //biuld the subtree with root b[l]
24 Node * BiuldSubtree(int d){
25 Node * tmp = new Node;
26 tmp->c = b[pos--]; //set node's symbol
27 tmp->d = d; //set node's depth
28 if(d > dep) dep = d; //renew depth of tree
29 if(tmp->c >= 'a' && tmp->c <= 'z')
30 tmp->l = tmp->r = NULL; //leaf nodes (variables)
31 else{ //branch nodes (operators)
32 tmp->r = BiuldSubtree(d+1);
33 tmp->l = BiuldSubtree(d+1);
34 }
35 return tmp;
36 }
37 //Biuld binary tree
38 void BiuldTree(){
39 pos = len-1; //current position of b[]
40 root = BiuldSubtree(0);
41 //printf("depth = %d
", dep);
42 }
43 //delete Tree
44 void DelTree(Node * ptr){
45 if(ptr == NULL) return;
46 DelTree(ptr->l);
47 DelTree(ptr->r);
48 delete ptr;
49 }
50 //Draw the subtree ptr pointing to from (si, sj) in pic[][]
51 void DrawSubtree(Node * ptr, int si, int sj){
52 if(ptr == NULL) return; //draw nothing
53 int i = si, j = sj + (1<<(dep-ptr->d)) - 1;
54 pic[i][j] = ptr->c;
55 if(ptr->l == NULL) return; //leaf node
56 pic[i+1][j-1] = '/';
57 pic[i+1][j+1] = '\';
58 DrawSubtree(ptr->l, i+2, sj);
59 DrawSubtree(ptr->r, i+2, j+1);
60 }
61 //print binary tree
62 void PrintTree(){
63 int h = dep*2+1, w = 1<<(dep+1);
64 int i, j;
65 //initialize pic[][]
66 pic = new char * [h];
67 for(i = 0 ; i < h; ++i){
68 pic[i] = new char[w];
69 for(j = 0; j < w; ++j)
70 pic[i][j] = ' ';
71 }
72 //draw nodes in pic[][]
73 DrawSubtree(root, 0, 0);
74 //don't print ending spaces
75 for(i = 0 ; i < h; ++i){
76 for(j = w-1; pic[i][j] == ' '; --j);
77 pic[i][j+1] = '