天梯赛2016-L2
Posted Penn000
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了天梯赛2016-L2相关的知识,希望对你有一定的参考价值。
L2-001. 紧急救援
作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。
输入格式:
输入第一行给出4个正整数N、M、S、D,其中N(2<=N<=500)是城市的个数,顺便假设城市的编号为0~(N-1);M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。
输出格式:
第一行输出不同的最短路径的条数和能够召集的最多的救援队数量。第二行输出从S到D的路径中经过的城市编号。数字间以空格分隔,输出首尾不能有多余空格。
输入样例:4 5 0 3 20 30 40 10 0 1 1 1 3 2 0 3 3 0 2 2 2 3 2输出样例:
2 60 0 1 3
1 //2017-03-17 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <queue> 6 #include <stack> 7 8 using namespace std; 9 10 const int N = 510; 11 const int inf = 0x3f3f3f3f; 12 int n, m, G[N][N], dis[N], vis[N], pre[N], way[N], maxpeo[N]; 13 14 int dijkstra(int s, int d) 15 { 16 for(int i = 0; i < n; i++) 17 { 18 dis[i] = G[s][i]; 19 if(G[s][i] != inf){ 20 pre[i] = s; 21 way[i]++; 22 } 23 } 24 pre[s] = -1; 25 dis[s] = 0; 26 vis[s] = 1; 27 way[s] = 1; 28 int mindis, u; 29 maxpeo[s] = G[s][s]; 30 for(int i = 0; i < n; i++) 31 { 32 mindis = inf; 33 for(int j = 0; j < n; j++) 34 if(!vis[j] && dis[j] < mindis) 35 { 36 mindis = dis[j]; 37 u = j; 38 } 39 vis[u] = 1; 40 for(int v = 0; v < n; v++) 41 { 42 if(vis[v] || G[u][v]==inf)continue; 43 if(dis[v] > dis[u]+G[u][v]){ 44 dis[v] = dis[u]+G[u][v]; 45 pre[v] = u; 46 maxpeo[v] = maxpeo[u] + G[v][v]; 47 way[v] = way[u]; 48 }else if(dis[v] == dis[u]+G[u][v]){ 49 way[v] += way[u]; 50 if(maxpeo[v] < maxpeo[u]+G[v][v]){ 51 maxpeo[v] = maxpeo[u] + G[v][v]; 52 pre[v] = u; 53 } 54 } 55 } 56 } 57 return maxpeo[d]+maxpeo[s]; 58 } 59 60 int main() 61 { 62 int s, d, u, v, w; 63 while(cin>>n>>m>>s>>d) 64 { 65 for(int i = 0; i < n; i++) 66 { 67 for(int j = 0; j < n; j++) 68 G[i][j] = inf; 69 vis[i] = 0; 70 dis[i] = inf; 71 pre[i] = -1; 72 way[i] = 0; 73 maxpeo[i] = 0; 74 cin>>G[i][i]; 75 maxpeo[i] = G[i][i]; 76 } 77 for(int i = 0; i < m; i++) 78 { 79 cin>>u>>v>>w; 80 G[u][v] = G[v][u] = w; 81 } 82 int peo = dijkstra(s, d); 83 int pr = d; 84 stack<int> sk; 85 while(pr != s) 86 { 87 sk.push(pr); 88 pr = pre[pr]; 89 } 90 cout<<way[d]<<" "<<peo<<endl; 91 cout<<s; 92 int o; 93 while(!sk.empty()) 94 { 95 o = sk.top(); 96 cout<<" "<<o; 97 sk.pop(); 98 } 99 cout<<endl; 100 } 101 102 return 0; 103 }
L2-002. 链表去重
给定一个带整数键值的单链表L,本题要求你编写程序,删除那些键值的绝对值有重复的结点。即对任意键值K,只有键值或其绝对值等于K的第一个结点可以被保留。同时,所有被删除的结点必须被保存在另外一个链表中。例如:另L为21→-15→-15→-7→15,则你必须输出去重后的链表21→-15→-7、以及被删除的链表-15→15。
输入格式:
输入第一行包含链表第一个结点的地址、以及结点个数N(<= 105 的正整数)。结点地址是一个非负的5位整数,NULL指针用-1表示。
随后N行,每行按下列格式给出一个结点的信息:
Address Key Next
其中Address是结点的地址,Key是绝对值不超过104的整数,Next是下一个结点的地址。
输出格式:
首先输出去重后的链表,然后输出被删除结点组成的链表。每个结点占一行,按输入的格式输出。
输入样例:00100 5 99999 -7 87654 23854 -15 00000 87654 15 -1 00000 -15 99999 00100 21 23854输出样例:
00100 21 23854 23854 -15 99999 99999 -7 -1 00000 -15 87654 87654 15 -1
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <list> 6 7 using namespace std; 8 9 const int N = 1e6+10; 10 int ne[N], ke[N], book[10005]; 11 struct node 12 { 13 int add, key, next; 14 void setNode(int a, int k, int n){ 15 this->add = a; 16 this->key = k; 17 this->next = n; 18 } 19 }; 20 21 int main() 22 { 23 int s, n, pos; 24 while(cin>>s>>n) 25 { 26 int ad; 27 for(int i = 0; i < n; i++) 28 { 29 cin>>ad; 30 cin>>ke[ad]>>ne[ad]; 31 } 32 list<node> l1, l2; 33 list<node>::iterator it; 34 node tmp; 35 memset(book, 0, sizeof(book)); 36 pos = s; 37 book[abs(s)] = 1; 38 tmp.setNode(pos, ke[pos], ne[pos]); 39 l1.push_back(tmp); 40 pos = ne[pos]; 41 while(pos != -1) 42 { 43 if(book[abs(ke[pos])]){ 44 if(!l2.empty()){ 45 tmp = l2.back(); 46 tmp.next = pos; 47 l2.pop_back(); 48 l2.push_back(tmp); 49 } 50 tmp.setNode(pos, ke[pos], ne[pos]); 51 l2.push_back(tmp); 52 }else{ 53 book[abs(ke[pos])] = 1; 54 if(!l1.empty()){ 55 tmp = l1.back(); 56 tmp.next = pos; 57 l1.pop_back(); 58 l1.push_back(tmp); 59 } 60 tmp.setNode(pos, ke[pos], ne[pos]); 61 l1.push_back(tmp); 62 } 63 pos = ne[pos]; 64 } 65 tmp = l1.back(); tmp.next = -1; 66 l1.pop_back();l1.push_back(tmp); 67 for(it = l1.begin(); it != l1.end(); it++){ 68 if(it->next == -1)printf("%05d %d %d\\n", it->add, it->key, it->next); 69 else printf("%05d %d %05d\\n", it->add, it->key, it->next); 70 } 71 if(!l2.empty()){ 72 tmp = l2.back(); tmp.next = -1; 73 l2.pop_back();l2.push_back(tmp); 74 } 75 for(it = l2.begin(); it != l2.end(); it++){ 76 if(it->next == -1)printf("%05d %d %d\\n", it->add, it->key, it->next); 77 else printf("%05d %d %05d\\n", it->add, it->key, it->next); 78 } 79 } 80 81 return 0; 82 }
L2-003. 月饼
月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需求量,请你计算可以获得的最大收益是多少。
注意:销售时允许取出一部分库存。样例给出的情形是这样的:假如我们有3种月饼,其库存量分别为18、15、10万吨,总售价分别为75、72、45亿元。如果市场的最大需求量只有20万吨,那么我们最大收益策略应该是卖出全部15万吨第2种月饼、以及5万吨第3种月饼,获得 72 + 45/2 = 94.5(亿元)。
输入格式:
每个输入包含1个测试用例。每个测试用例先给出一个不超过1000的正整数N表示月饼的种类数、以及不超过500(以万吨为单位)的正整数D表示市场最大需求量。随后一行给出N个正数表示每种月饼的库存量(以万吨为单位);最后一行给出N个正数表示每种月饼的总售价(以亿元为单位)。数字间以空格分隔。
输出格式:
对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后2位。
输入样例:3 20 18 15 10 75 72 45输出样例:
94.50
1 //2017-03-18 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 7 using namespace std; 8 9 const int N = 1005; 10 struct node{ 11 double a, b; 12 double c; 13 bool operator < (const node& x){ 14 return c > x.c; 15 } 16 }moom[N]; 17 18 int main() 19 { 20 int n, need; 21 while(cin>>n>>need) 22 { 23 for(int i = 0; i < n; i++) 24 cin>>moom[i].a; 25 for(int i = 0; i < n; i++) 26 cin>>moom[i].b; 27 for(int i = 0; i < n; i++) 28 moom[i].c = moom[i].b*1.0/moom[i].a; 29 sort(moom, moom+n); 30 double ans = 0; 31 for(int i = 0; i < n; i++) 32 { 33 if(need < moom[i].a){ 34 ans += moom[i].c*need; 35 break; 36 }else{ 37 ans += moom[i].b; 38 need -= moom[i].a; 39 } 40 } 41 printf("%.2lf\\n", ans); 42 } 43 44 return 0; 45 }
L2-004. 这是二叉搜索树吗?
一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点,
- 其左子树中所有结点的键值小于该结点的键值;
- 其右子树中所有结点的键值大于等于该结点的键值;
- 其左右子树都是二叉搜索树。
所谓二叉搜索树的“镜像”,即将所有结点的左右子树对换位置后所得到的树。
给定一个整数键值序列,现请你编写程序,判断这是否是对一棵二叉搜索树或其镜像进行前序遍历的结果。
输入格式:
输入的第一行给出正整数N(<=1000)。随后一行给出N个整数键值,其间以空格分隔。
输出格式:
如果输入序列是对一棵二叉搜索树或其镜像进行前序遍历的结果,则首先在一行中输出“YES”,然后在下一行输出该树后序遍历的结果。数字间有1个空格,一行的首尾不得有多余空格。若答案是否,则输出“NO”。
输入样例1:7 8 6 5 7 10 8 11输出样例1:
YES 5 7 6 8 11 10 8输入样例2:
7 8 10 11 8 6 7 5输出样例2:
YES 11 8 10 7 5 6 8输入样例3:
7 8 6 8 5 10 9 11输出样例3:
NO
1 //2017-03-19 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 6 using namespace std; 7 8 const int N = 1005; 9 int bt[N], bst1[N], bst2[N], ANS[N], n, cnt; 10 struct node{ 11 int data; 12 node *lson, *rson; 13 node(int d):data(d), lson(NULL), rson(NULL){} 14 }; 15 16 class BST 17 { 18 public: 19 node *rt; 20 BST():rt(NULL){} 21 void insert(int a) 22 { 23 node* nd = new node(a); 24 if(rt == NULL){ 25 rt = nd; 26 }else{ 27 node *p = rt, *q = NULL; 28 while(p != NULL){ 29 q = p; 30 if(a < p->data){ 31 p = p->lson; 32 }else{ 33 p = p->rson; 34 } 35 } 36 if(a < q->data)q->lson = nd; 37 else q->rson = nd; 38 } 39 } 40 }; 41 42 void preOrder1(node* id) 43 { 44 if(id != NULL) 45 { 46 bst1[cnt] = id->data; 47 cnt++; 48 preOrder1(id->lson); 49 preOrder1(id->rson); 50 } 51 } 52 53 void preOrder2(node* id) 54 { 55 if(id != NULL) 56 { 57 bst2[cnt] = id->data; 58 cnt++; 59 preOrder2(id->rson); 60 preOrder2(id->lson); 61 } 62 } 63 64 void postOrder1(node* id) 65 { 66 if(id != NULL){ 67 postOrder1(id->lson); 68 postOrder1(id->rson); 69 ANS[cnt] = id->data; 70 cnt++; 71 } 72 } 73 74 void postOrder2(node* id) 75 { 76 if(id != NULL){ 77 postOrder2(id->rson); 78 postOrder2(id->lson); 79 ANS[cnt] = id->data; 80 cnt++; 81 } 82 } 83 84 int main() 85 { 86 while(cin>>n) 87 { 88 BST bst; 89 for(int i = 0; i < n; i++) 90 { 91 cin>>bt[i]; 92 bst.insert(bt[i]); 93 } 94 cnt = 0; 95 preOrder1(bst.rt); 96 cnt = 0; 97 preOrder2(bst.rt); 98 bool fg1 = true, fg2 = true; 99 for(int i = 0; i < n; i++){ 100 if(bt[i] != bst1[i])fg1 = false; 101 if(bt[i] != bst2[i])fg2 = false; 102 } 103 if(fg1){ 104 cout<<"YES"<<endl; 105 cnt = 0; 106 postOrder1(bst.rt); 107 for(int i = 0; i < n; i++) 108 if(i == n-1)cout<<ANS[i]<<endl; 109 else cout<<ANS[i]<<" "; 110 }else if(fg2){ 111 cout<<"YES"<<endl; 112 cnt = 0; 113 postOrder2(bst.rt); 114 for(int i = 0; i < n; i++) 115 if(i == n-1)cout<<ANS[i]<<endl; 116 else cout<<ANS[i]<<" "; 117 }else cout<<"NO"<<endl; 118 } 119 120 return 0; 121 }
L2-005. 集合相似度
给定两个整数集合,它们的相似度定义为:Nc/Nt*100%。其中Nc是两个集合都有的不相等整数的个数,Nt是两个集合一共有的不相等整数的个数。你的任务就是计算任意一对给定集合的相似度。
输入格式:
输入第一行给出一个正整数N(<=50),是集合的个数。随后N行,每行对应一个集合。每个集合首先给出一个正整数M(<=104),是集合中元素的个数;然后跟M个[0, 109]区间内的整数。
之后一行给出一个正整数K(<=2000),随后K行,每行对应一对需要计算相似度的集合的编号(集合从1到N编号)。数字间以空格分隔。
输出格式:
对每一对需要计算的集合,在一行中输出它们的相似度,为保留小数点后2位的百分比数字。
输入样例:3 3 99 87 101 4 87 101 5 87 7 99 101 18 5 135 18 99 2 1 2 1 3输出样例:
50.00% 33.33%
1 //2017-03-19 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 #include <set> 7 8 using namespace std; 9 10 int se[55][1005], cnt[55]; 11 12 double merge(int a, int b) 13 { 14 int nt = 0, nc = 0; 15 int cnt1 = 0, cnt2 = 0; 16 while(cnt1 < cnt[a] && cnt2 < cnt[b]) 17 { 18 if(se[a][cnt1] < se[b][cnt2]){ 19 nt++; 20 cnt1++; 21 }else if(se[a][cnt1] > se[b][cnt2]){ 22 nt++L1-027 出租 (20 分)天梯赛C++和python 代码