Ⅰ 排序算法
#include<bits/stdc++.h>
using namespace std;
bool my_less(int i, int j) {return (i < j);} //自定义小于
bool my_greater(int i, int j) {return (i > j);} //自定义大于
int main (){
vector<int> a = {3,7,2,5,6,8,5,4};
sort(a.begin(),a.begin()+4); //对前4个排序,输出2 3 5 7 6 8 5 4
//sort(a.begin(),a.end()); //从小到大排序, 输出2 3 4 5 5 6 7 8
//sort(a.begin(),a.end(),less<int>()); //输出2 3 4 5 5 6 7 8
//sort(a.begin(),a.end(),my_less); //自定义排序,输出 2 3 4 5 5 6 7 8
//sort(a.begin(),a.end(),greater<int>()); //从大到小排序,输出 8 7 6 5 5 4 3 2
//sort(a.begin(),a.end(),my_greater); // 输出 8 7 6 5 5 4 3 2
for(int i=0; i<a.size(); i++) cout<<a[i]<< " "; //输出
return 0;
}
例1 奖学金 洛谷P1093
yi
NOIP2007 普及组 T1
题目描述
某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前 55 名学生发奖学金。期末,每个学生都有 33 门课的成绩:语文、数学、英语。先按总分从高到低排序,如果两个同学总分相同,再按语文成绩从高到低排序,如果两个同学总分和语文成绩都相同,那么规定学号小的同学排在前面,这样,每个学生的排序是唯一确定的。
任务:先根据输入的 33 门课的成绩计算总分,然后按上述规则排序,最后按排名顺序输出前五名名学生的学号和总分。
注意,在前 55 名同学中,每个人的奖学金都不相同,因此,你必须严格按上述规则排序。例如,在某个正确答案中,如果前两行的输出数据(每行输出两个数:学号、总分) 是:
7 279
5 279
这两行数据的含义是:总分最高的两个同学的学号依次是 77 号、55 号。这两名同学的总分都是 279279 (总分等于输入的语文、数学、英语三科成绩之和) ,但学号为 77 的学生语文成绩更高一些。
如果你的前两名的输出数据是:
5 279
7 279
则按输出错误处理,不能得分。
输入格式
共 𝑛+1n+1 行。
第 11 行为一个正整数 𝑛≤300n≤300,表示该校参加评选的学生人数。
第 22 到 𝑛+1n+1 行,每行有 33 个用空格隔开的数字,每个数字都在 00 到 100100 之间。第 𝑗j 行的 33 个数字依次表示学号为 𝑗−1j−1 的学生的语文、数学、英语的成绩。每个学生的学号按照输入顺序编号为 1∼𝑛1∼n(恰好是输入数据的行号减 11)。
保证所给的数据都是正确的,不必检验。
输出格式
共 55 行,每行是两个用空格隔开的正整数,依次表示前 55 名学生的学号和总分。
#include<bits/stdc++.h>
using namespace std;
struct stu{
int id; //学号
int c,m,e; //语、数、外
int sum;
}st[305];
bool cmp(stu a,stu b){
if(a.sum > b.sum) return true;
else if(a.sum < b.sum) return false;
else{ //a.sum == b.sum
if(a.c > b.c) return true;
else if(a.c < b.c) return false;
else{ //a.c == b.c
if(a.id > b.id) return false;
else return true;
}
}
}
int main(){
int n; cin>>n;
for(int i=1;i<=n;i++){
st[i].id = i; //学号
cin >> st[i].c >> st[i].m >> st[i].e;
st[i].sum = st[i].c + st[i].m + st[i].e; //总分
}
sort(st+1,st+1+n,cmp); //用cmp()排序
for(int i=1;i<=5;i++) cout << st[i].id << ' ' << st[i].sum << endl;
return 0;
}
Ⅱ 排列
自写排列函数
#include<bits/stdc++.h>
using namespace std;
int a[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13};
bool vis[20]; //记录第i个数是否用过
int b[20]; //生成的一个全排列
void dfs(int s,int t){
if(s == t) { //递归结束,产生一个全排列
for(int i = 0; i < t; ++i) cout << b[i] << " "; //输出一个排列
cout<<endl;
return;
}
for(int i=0;i<t;i++)
if(!vis[i]){
vis[i] = true;
b[s] = a[i];
dfs(s+1,t);
vis[i] = false;
}
}
int main(){
int n = 3;
dfs(0,n); //前n个数的全排列
return 0;
}
例Ⅰ 蓝桥杯2016年省赛C++A组第6题
#include <bits/stdc++.h>
using namespace std;
int a[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
int main() {
int ans=0;
do{ if( a[0]+a[1]==a[2] && a[3]-a[4]==a[5]
&&a[6]*a[7]==a[8] && a[11]*a[10]==a[9])
ans++;
}while(next_permutation(a,a+13));
cout<<ans<<endl;
}
#include<bits/stdc++.h>
using namespace std;
int a[20]={1,2,3,4,5,6,7,8,9,10,11,12,13};
bool vis[20];
int b[20];
int ans=0;
void dfs(int s,int t){
if(s==12) {
if(b[9]*b[10] == b[11]) ans++;
return;
}
if(s==3 && b[0]+b[1]!=b[2]) return; //剪枝
if(s==6 && b[3]-b[4]!=b[5]) return; //剪枝
if(s==9 && b[6]*b[7]!=b[8]) return; //剪枝
for(int i=0;i<t;i++)
if(!vis[i]){
vis[i]=true;
b[s]=a[i]; //本题不用a[],改成b[s]=i+1也行
dfs(s+1,t);
vis[i]=false;
}
}
int main(){
int n=13;
dfs(0,n); //前n个数的全排列
cout<<ans;
return 0;
}
例2. 汉诺塔
#include<bits/stdc++.h>
using namespace std;
int sum = 0, m;
void hanoi(char x,char y,char z,int n){ //三个柱子x、y、z
if(n==1) { //最小问题
sum++;
if(sum==m) cout<<"#"<<n<<": "<<x<<"->"<<z<<endl;
}
else { //分治
hanoi(x,z,y,n-1); //(1)先把x的n-1个小盘移到y,然后把第n个大盘移到z
sum++;
if(sum==m) cout<<"#"<<n<<": "<<x<<"->"<<z<<endl;
hanoi(y,x,z,n-1); //(2)把y的n-1个小盘移到z
}
}
int main(){
int n; cin>>n>>m;
hanoi('A','B','C',n);
cout<<sum<<endl;
return 0;
}
例三 快速幂
#include<bits/stdc++.h>
using namespace std;
typedef long long ll; //注意要用long long,用int会出错
ll fastPow(ll a, ll n,ll m){ //an mod m
if(n == 0) return 1; //特判 a0 = 1
if(n == 1) return a;
ll temp = fastPow(a, n/2,m); //分治
if(n%2 == 1) return temp * temp * a % m; //奇数个a。也可以这样写: if(n &1)
else return temp * temp % m ; //偶数个a
}
int main(){
ll a,n,m; cin >> a >> n>> m;
cout << fastPow(a,n,m);
return 0;
}