1. 程式人生 > >資訊學奧賽一本通(C++版)第二部分 基礎演算法 第二章 資料排序

資訊學奧賽一本通(C++版)第二部分 基礎演算法 第二章 資料排序

第二章 資料排序

T1310 : 車廂重組

時間限制: 1000 ms 記憶體限制: 65536 KB

【題目描述】

  在一箇舊式的火車站旁邊有一座橋,其橋面可以繞河中心的橋墩水平旋轉。一個車站的職工發現橋的長度最多能容納兩節車廂,如果將橋旋轉180180度,則可以把相鄰兩節車廂的位置交換,用這種方法可以重新排列車廂的順序。於是他就負責用這座橋將進站的車廂按車廂號從小到大排列。他退休後,火車站決定將這一工作自動化,其中一項重要的工作是編一個程式,輸入初始的車廂順序,計算最少用多少步就能將車廂排序。

【輸入】

  有兩行資料,第一行是車廂總數N(N10000)N(N≤10000),第二行是NN個不同的數表示初始的車廂順序。

【輸出】

  一個數據,是最少的旋轉次數。

【輸入樣例】

4
4 3 2 1

【輸出樣例】

6

【答案&程式碼】

  顯然,題意說明,我們只能將相鄰的車廂位置交換,這顯然是氣泡排序的實現過程,所以這道題目,應該用氣泡排序來解決,程式碼如下。

#include<stdio.h>
void swap(int *a,int *b){/*交換a,b的值*/
	int temp=*a;
	*a=*b;
	*b=temp;
	return;
}
int main(void){
	int n;
	scanf("%d",&n);
	int box[n];
	for(int i=0;
i<n;i++) scanf("%d",&box[i]); int sum=0; for(int i=1;i<n;i++) for(int j=0;j<i;j++) if(box[i]<box[j]){ swap(&box[i],&box[j]); sum+=1;/*每交換1次,交換次數加1*/ } printf("%d",sum); return 0; }

T1311 : 求逆序對

時間限制: 1000 ms 記憶體限制: 65536 KB

【題目描述】

  給定一個序列a1,a2,...,ana_{1},a_{2},...,a_{n}

如果存在i&lt;ji&lt;j並且ai&gt;aja_{i}&gt;a_{j},那麼我們稱之為逆序對,求逆序對的數目。

【輸入】

  第一行為nn,表示序列長度,接下來的nn行,第i+1i+1行表示序列中的第ii個數。

【輸出】

  所有逆序對總數。

【輸入樣例】

4
3
2
3
2

【輸出樣例】

3

【提示】

  N105,Ai105N≤10^5,A_{i}≤10^5

【答案&程式碼】

  通過理性分析,我們可以得出,用所有的排序演算法都可以完成本題,只需要統計每一個數所構成的逆序對個數即可,但是因為氣泡排序、插入排序等排序演算法時間複雜度為O(n2)O(n^{2}),快速排序不穩定,此題應選用歸併排序,程式碼如下。

#include<stdio.h>
int n,a[100001],c[100001];
unsigned long long ans=0;
void m(int l,int r){
	int mid=(l+r)/2,i,j,tmp;
	if(l>=r)
		return;
	m(l,mid);
	m(mid+1,r);
	tmp=l;
	for(i=l,j=mid+1;i<=mid&&j<=r;)
		if(a[i]>a[j])
			c[tmp++]=a[j++],ans+=mid-i+1;
		else c[tmp++]=a[i++];
	if(i<=mid)
		for(;i<=mid;)
			c[tmp++]=a[i++];
	if(j<=r)
		for(;j<=r;)
			c[tmp++]=a[j++];
	for(i=l;i<=r;i++)
		a[i]=c[i];
}
int main(void){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",a+i);
	m(1,n);
	printf("lld",ans);
	return 0;
}

T1176 : 誰考了第k名

時間限制: 1000 ms 記憶體限制: 65536 KB

【題目描述】

  在一次考試中,每個學生的成績都不相同,現知道了每個學生的學號和成績,求考第kk名學生的學號和成績。

【輸入】

  第一行有兩個整數,分別是學生的人數n(1n100)n(1≤n≤100),和求第kk名學生的k(1kn)k(1≤k≤n)

  其後有nn行資料,每行包括一個學號(整數)和一個成績(浮點數),中間用一個空格分隔。

【輸出】

  輸出第kk名學生的學號和成績,中間用空格分隔。(注:請用%g輸出成績)

【輸入樣例】

5 3
90788001 67.8
90788002 90.3
90788003 61
90788004 68.4
90788005 73.9

【輸出樣例】

90788004 68.4

【答案&程式碼】

  顯然,對於每11個已知的學號,都有且只有11個成績,所以我們可以使用結構體來解決這道題,結構體進行排序(運用<algorithm>中的std::sort函式)需要<運算子進行過載運用自定義的比較函式,程式碼如下。

#include<stdio.h>
#include<algorithm>
struct st{
	char id[16];
	double gr;
};
bool cmp(st a,st b){
	return a.gr>b.gr;
}
int main(void){
	int n,k;
	scanf("%d%d",&n,&k);
	st stu[n];
	for(int i=0;i<n;i++)
		scanf("%s%lf",stu[i].id,&stu[i].gr);
	std::sort(stu,stu+n,cmp);
	printf("%s %g",stu[k-1].id,stu[k-1].gr);
	return 0;
}

T1177 : 奇數單增序列

時間限制: 1000 ms 記憶體限制: 65536 KB

【題目描述】

  給定一個長度為NN(不大於500500)的正整數序列,請將其中的所有奇數取出,並按升序輸出

【輸入】

  第11行為NN

  第22行為NN個正整數,其間用空格間隔。

【輸出】

  增序輸出的奇數序列,資料之間以逗號間隔。資料保證至少有一個奇數。

【輸入樣例】

10
1 3 2 6 5 4 9 8 7 10

【輸出樣例】

1,3,5,7,9

【答案&程式碼】

  我們只需要在輸入的時候使用一些小技巧,將偶數去除,再將陣列排序輸出即可,程式碼如下。

#include<stdio.h>
#include<algorithm>
int main(void){
	int n;
	scanf("%d",&n);
	int num[n];
	for(int i=0;i<n;i++){
		scanf("%d",&num[i]);
		if(num[i]%2==0)
			i--,n--;
	}
	std::sort(num,num+n);
	printf("%d",num[0]);
	for(int i=1;i<n;i++)
		printf(",%d",num[i]);
	return 0;
}

T1178 : 成績排序

時間限制: 1000 ms 記憶體限制: 65536 KB

【題目描述】

  給出班裡某門課程的成績單,請你按成績從高到低對成績單排序輸出,如果有相同分數則名字字典序小的在前。

【輸入】

  第一行為n(0&lt;n&lt;20)n(0&lt;n&lt;20),表示班裡的學生數目;

  接下來的nn行,每行為每個學生的名字和他的成績,中間用單個空格隔開。名字只包含字母且長度不超過2020,成績為一個不大於100100的非負整數。

【輸出】

  把成績單按分數從高到低的順序進行排序並輸出,每行包含名字和分數兩項,之間有一個空格。

【輸入樣例】

4
Kitty 80
Hanmeimei 90
Joey 92
Tim 28

【輸出樣例】

Joey 92
Hanmeimei 90 
Kitty 80
Tim 28

【答案&程式碼】

  思路與T1176類似,程式碼如下。

#include<stdio.h>
#include<string.h>
#include<algorithm>
struct st{
	char id[16];
	int gr;
};
bool cmp(st a,st b){
	if(a.gr==b.gr)
		return strcmp(a.id,b.id)==-1;
	else
		return a.gr>b.gr;
}
int main(void){
	int n;
	scanf("%d",&n);
	st stu[n];
	for(int i=0;i<n;i++)
		scanf("%s%d",stu[i].id,&stu[i].gr);
	std::sort(stu,stu+n,cmp);
	for(int i=0;i<n;i++)
		printf("%s %d\n",stu[i].id,stu[i].gr);
	return 0;
}

T1179 : 獎學金

時間限制: 1000 ms 記憶體限制: 65536 KB

【題目描述】

  某小學最近得到了一筆贊助,打算拿出其中一部分為學習成績優秀的前55名學生髮獎學金。期末,每個學生都有33門課的成績:語文、數學、英語。先按總分從高到低排序,如果兩個同學總分相同,再按語文成績從高到低排序,如果兩個同學總分和語文成績都相同,那麼規定學號小的同學排在前面,這樣,每個學生的排序是唯一確定的。

  任務:先根據輸入的33門課的成績計算總分,然後按上述規則排序,最後按排名順序輸出前五名學生的學號和總分。注意,在前55名同學中,每個人的獎學金都不相同,因此,你必須嚴格按上述規則排序。例如,在某個正確答案中,如果前兩行的輸出資料(每行輸出兩個數:學號、總分)是:

7 279
5 279

  這兩行資料的含義是:總分最高的兩個同學的學號依次是77號、55號。這兩名同學的總分都是279279(總分等於輸入的語文、數學、英語三科成績之和),但學號為77的學生語文成績更高一些。如果你的前兩名的輸出資料是:

5 279
7 279

  則按輸出錯誤處理,不能得分。

【輸入】

  包含n+1n+1行:

  第11行為一個正整數nn(小於300300),表示該校參加評選的學生人數。

  第22n+1n+1行,每行有33個用空格隔開的數字,每個數字都在00100100之間。第jj行的33個數字依次表示學號為j1j-1的學生的語文、數學、英語的成績。每個學生的學號按照輸入順序編號為1n1-n(恰好是輸入資料的行號減11)。

【輸出】

  共有55行,每行是兩個用空格隔開的正整數,依次表示前55名學生的學號和總分。

【輸入樣例1】

6
90 67 80
87 66 91
78 89 91
88 99 77
67 89 64
78 89 98

【輸出樣例1】

6 265
4 264
3 258
2 244
1 237

【輸入樣例2】

8
80 89 89
88 98 78
90 67 80
87 66 91
78 89 91
88 99 77
67 89 64
78 89 98

【輸出樣例2】

8 265
2 264
6 264
1 258
5 258

【答案&程式碼】

  程式碼如下。

#include<stdio.h>
#include<string.h>
#include<algorithm>
struct node{
	int id,Ch,Ma,En;
};
bool cmp(node a,node b){
	if(a.Ch+a.Ma+a.En==b.Ch+b.Ma+b.En)
		if(a.Ch==b.Ch)
			return a.id<b.id;
		else
			return a.Ch>b.Ch;
	else
		return a.Ch+a.Ma+a.En>b.Ch+b.Ma+b.En;
}
int main(void){
	int n;
	scanf("%d",&n);
	node st[n];
	for(int i=0;i<n;i++){
		st[i].id=i+1;
		scanf("%d %d %d",&st[i].Ch,&st[i].Ma,&st[i].En);
	}
	std::sort(st,st+n,cmp
            
           

相關推薦

資訊奧賽C++第一部分 C++語言 第五 陣列

第五章 陣列 第一節 一維陣列 T1102 : 與指定數字相同的數的個數 時間限制: 1000 ms 記憶體限制: 65536 KB 【題目描述】   輸出一個整數序列中與指定數字相同的數的個數。 【輸入】   輸入包含三行:   第一行為N(N≤100)N

資訊奧賽C++第一部分 C++語言 第四 迴圈結構的程式設計

第四章 迴圈結構的程式設計 第一節 for語句 T1059 : 求平均年齡 時間限制: 1000 ms 記憶體限制: 65536 KB 【題目描述】   班上有學生若干名,給出每名學生的年齡(整數),求班上所有學生的平均年齡,保留到小數點後兩位。 【輸入】

資訊奧賽C++ 第一部分 C++語言 第四 迴圈結構的程式設計

//1091 求階乘的和#include <stdio.h>int f(int n){    int i,ans=1;    for(i=1;i<=n;i++)        ans*=i;    return ans;}int main(){    int n,i,sum=0;    sc

資訊奧賽C++第一部分 C++語言 第三 程式的控制結構

第三章 程式的控制結構 第一節 if選擇結構 T1039 : 判斷數正負 【題目描述】   給定一個整數NNN,判斷其正負。如果N&gt;0N&gt;0N>0,輸出positive;如果N=0N=0N=0,輸出zero;如果N&lt

資訊奧賽C++

2018年資訊學奧賽NOIP資料下載 資訊學奧賽一本通(C++版) 第一部分 C++語言 第一章 C++語言入門 //1000 入門測試題目 #include <stdio.h> int main(){ int a,b; scanf("%d%d",&a,&b)

資訊奧賽C++第二部分 基礎演算法 第一 高精度計算

第一章 高精度計算 模板在最後。 T1307 : 高精度乘法 時間限制: 1000 ms 記憶體限制: 65536 KB 【題目描述】 【輸入】 【輸出】 【輸入樣例】 【輸出樣例】 【答案&程式碼】 T1308 : 高精除 時間限制:

資訊奧賽C++ 第三部分 資料結構 第三

//1336 【例3-1】找樹根和孩子 //提交,未通過,明白了,孩子必須按字典序輸出 //修改,提交,AC 2017-12-13 18:54 //該題思路可以預計,與書中提供的程式碼很不相同,書中猜測用的是左子右兄表示法,日後驗證 //該題,本人思路,鄰接表,有向圖. //很明顯,水平上了一個臺階。 #i

資訊奧賽C++ 第三部分 資料結構 第二 佇列

//1334 【例2-3】圍圈報數//迴圈佇列,取模,數列空出一個空間//提交,未通過,執行超時//90分程式碼 #include <stdio.h>int q[10000];int main(){    int n,m,h,t,i,mod;    scanf("%d%d",&n,&

資訊奧賽C++ 第二部分 基礎演算法 第八 廣度優先搜尋算

//1329 【例8.2】細胞//編寫過程中,發現輸入資料用整數無法讀取,要採用字串形式//核心思路,將非零數字字元改成0字元 //將程式碼修改,提交AC #include <stdio.h>int n,m,next[][2]={{1,0},{-1,0},{0,1},{0,-1}};char a[

資訊奧賽C++ 第二部分 基礎演算法 第一 高精度計算

//1307 【例1.3】高精度乘法 //手動模擬乘法運算 //提交,測試點5,答案錯誤,猜測,應該是0的情況,沒考慮 //提供一組測試資料 //輸入: //123 //0 //輸出: //0 //考慮了0的情況,修改,提交AC 2017-11-9 //編到這裡,感覺高精度加是高精度演算法的基礎 #inc

資訊奧賽C++ 第二部分 基礎演算法 第四 遞迴演算法

//1206 放蘋果 遞迴 //1192 放蘋果//http://www.cnblogs.com/dongsheng/archive/2012/08/15/2640468.html此文介紹得不錯,摘抄如下://8    解題分析://9         設f(m,n) 為m個蘋果,n個盤子的放法數目,則先對n

資訊奧賽C++ 網站補充題目

//1414 【2017NOIP普及組】成績 //樣例通過,提交AC 2017-12-31 21:45 #include <stdio.h> int main(){     int a,b,c;     scanf("%d%d%d",&a,&b,&c);     prin

資訊奧賽C++第二部分 基礎演算法 第二 資料排序

第二章 資料排序 T1310 : 車廂重組 時間限制: 1000 ms 記憶體限制: 65536 KB 【題目描述】   在一箇舊式的火車站旁邊有一座橋,其橋面可以繞河中心的橋墩水平旋轉。一個車站的職工發現橋的長度最多能容納兩節車廂,如果將橋旋轉180180

資訊奧賽C++ 第三部分 資料結構 第四 圖論演算法

 資訊學奧賽一本通(C++版) 第三部分 資料結構   第四章 圖論演算法 http://ybt.ssoier.cn:8088/ 第一節 圖的遍歷 //1341 【例題】一筆畫問題 //在想,是輸出尤拉路,還是歐拉回路 //從哪點開始遍歷, //點的資料範圍,邊的資料範圍

資訊奧賽演算法C++基礎演算法:高精度計算 高精度加法(大位相加)

2018年資訊學奧賽NOIP資料下載 1 #include <bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 char a1[100],b1[100]; 6 int a[100],b[100],c[100];/

C++資訊奧賽題庫1032

大象喝水查 時間限制: 1000 ms         記憶體限制: 65536 KB 提交數: 1472     通過數: 969 【題目描述】 一隻大象口渴了,要喝20升水才能解渴,但現在只有一個深h釐米,底面半徑為r釐米的小圓桶(h和r都是整數)。問大象至少要喝

資訊奧賽 小球drop

2018年資訊學奧賽NOIP資料下載 This drop is gonna last forever! 許多的小球一個一個的從一棵滿二叉樹上掉下來組成FBT(Full Binary Tree,滿二叉樹),每一時間,一個正在下降的球第一個訪問的是非葉子節點。然後繼續下降時,或者走右子樹,或

資訊奧賽 1299糖果#線性動態規劃#

題意:給出n個數,找出若干個數,使它們的和為k的倍數,並輸出最大的數。狀態轉移方程:f[i][j]表示前i個數%k=j的總數。f[i][j]=max(f[i-1][j],f[i-1][tmp]+a[i]

C++資訊奧賽題庫1036A*B問題

A*B問題 時間限制: 1000 ms         記憶體限制: 65536 KB 提交數: 3404     通過數: 956  【題目描述】 輸入兩個正整數A和B,求A*B的值。注意乘積的範圍和資料型別的選擇。 【輸入】 一行,包含兩個正整數A和B,中間用單個空格隔

C++資訊奧賽題庫1034計算三角形面積

計算三角形面積 時間限制: 1000 ms         記憶體限制: 65536 KB 提交數: 1813     通過數: 622  【題目描述】 平面上有一個三角形,它的三個頂點座標分別為(x1, y1), (x2, y2), (x3, y3),那麼請問這個三角形的