计算机考研复试机试重点问题总结
2020.8.21-2020.9.6 the first version
1 闰年
(year % 4 == 0 && year % 100 != 0) || (year % 400 = 0)
预处理每个月的天数,用空间换时间
int daytab[2][13]={
{0,31,28,31,30,31,30,31,31,30,31,30,31}
{0,31,29,31,30,31,30,31,31,30,31,30,31}
}
2 保留几位输出
3.C语言读取text文件
#include<iostream>
#include<stdio.h>
using namespace std;
int main(){
//逐行写
FILE *fp = NULL;
char buffw[26];
fp = fopen("1.txt", "w+");
for(int i=0;i<26;i++){
buffw[i]='a'+i;
}
//fprintf(fp, "This is testing for fprintf...\n");
fputs(buffw,fp);
fclose(fp);
//逐行读
//FILE *fp=NULL;
char buffr[255];
fp = fopen("D:\\devcpp\\baoyan\\1.txt", "r");
while(!feof(fp)){
fgets(buffr,255,fp);
// printf("%s\n", buff);
cout<<buffr;
}
fclose(fp);
}
c++读取文件首选#include<iostream>
#include<fstream>
#include<stdio.h>
using namespace std;
int main(){
//写入
fstream wfile;
wfile.open("1.txt");
char sdata[26];
for(int i=0;i<26;i++){
sdata[i]='z'-i;
wfile << sdata[i]<<endl;
}
//cout<<sdata<<endl;
wfile.close();
//读取
string data="";
fstream rfile;
rfile.open("1.txt");
//rfile.getline(data,27);//读取num-1个字符
while (getline(rfile,data))
cout << data << endl;
rfile.close();
return 0;
}
4.vector容器
//vector容器
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
vector<int>obj;
vector<int>::iterator it;
for(int i=5;i>=0;i--){
obj.push_back(i);
}
//sort(obj.begin(),obj.end());
for(it=obj.begin();it!=obj.end();it++){
cout<<*it<<" ";
}
return 0;
}
5 sort函数
sort(first,last,comp)
起始地址first,last
comp 排序方式默认升序
重写sort函数可以变为降序
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
bool compare(int a,int b) {
return a>b; //升序排列,如果改为return a>b,则为降序
}
int main(){
int n=5;
int arr[n];
for(int i = 0; i < n; i++){
scanf("%d",&arr[i]);
}
sort(arr,arr+n,compare);
for(int i = 0; i < n; i++){
printf("%d ",arr[i]);
}
return 0;
}
compare函数:比较函数,在遇到新的排序规则时,黄金法则:当比较函数返回值为true时,表示比较函数是第一个参会将排在第二个参数前面。
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
struct student{
string name;
int grade;
int order;
};
bool compare1(student a,student b){
if(a.grade==b.grade){
return a.order<b.order;
}
else{
return a.grade>b.grade;
}
}
bool compare2(student a,student b){
if(a.grade==b.grade){
return a.order<b.order;
}
else{
return a.grade<b.grade;
}
}
int main(){
int n;
int func;
cin>>n>>func;
student stu[n];
for(int i=0;i<n;i++){
cin>>stu[i].name>>stu[i].grade;
stu[i].order=i;
}
if(func==0){
sort(stu,stu+n,compare1);
}else{
sort(stu,stu+n,compare2);
}
for(int i=0;i<n;i++){
cout<<stu[i].name<<" "<<stu[i].grade<<endl;
}
return 0;
}
6.二分查找
在查找次数很多的情况下,二分查找优于线性查找
二分查找需要先排序,再查找;
while(left<=right){
注意二分法退出循环的条件。#include<iostream>
#include<algorithm>
using namespace std;
int BinarySearch(int a,int num[],int n){
int left=0;
int right=n-1;
int mid=(left+right)/2;
while(left<=right){
if(num[mid]==a){
return 1;
}
else if(num[mid]<a){
left=mid+1;
}else{
right=mid-1;
}
mid=(left+right)/2;
}
return 0;
}
int main(){
int n,m;
while(cin>>n){
int arr[n];
for(int i=0;i<n;i++){
cin>>arr[i];
}
sort(arr,arr+n);
cin>>m;
int num,target;
for(int i=0;i<m;i++){
cin>>num;
target=BinarySearch(num,arr,n);
if(target==1){
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
}
}
return 0;
}
7.字符串string
string
插入删除
长度
#include<iostream>
#include<string>
using namespace std;
int main(){
string str="Hello World!";
int n=str.length();//长度
str.insert(0, "zq");//把"zq"插入到位置"0"
//cout<<str;
str.erase(0,2);//删除从位置0开始的2个字符
str.clear();
cout<<str;
return 0;
}
常用函数
find()
没找到返回-1
substr()
下标从0开始
#include<iostream>
#include<string>
using namespace std;
int main(){
string str="Hello World!";
int found=str.find("Hello");
cout<<found<<endl;
string str1=str.substr(0,5);
cout<<str1;
return 0;
}
常见应用
- 字符串处理
巧用ASCII码计算
#include<iostream>
#include<string>
using namespace std;
int main(){
string str1,str2;
cin>>str1>>str2;
int len1,len2;
len1=str1.length();
len2=str2.length();
int sum=0;
for(int i=0;i<len1;i++){
for(int j=0;j<len2;j++){
sum=sum+(str1[i]-'0')*(str2[j]-'0');
}
}
cout<<sum;
return 0;
}
- getline()可以获取一行带空格的字符串,cin>>str遇到空格就会停止输入
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main(){
string str;
int sym;
while(getline(cin,str)){
for(int i=0;i<str.length();i++){
if(str[i]<='z'&&str[i]>='a'){
sym=str[i]-'a';
sym=(sym+1)%26;
str[i]='a'+sym;
}
if(str[i]<='Z'&&str[i]>='A'){
sym=str[i]-'A';
sym=(sym+1)%26;
str[i]='A'+sym;
}
}
for(int i=0;i<str.length();i++){
cout<<str[i];
}
cout<<endl;
}
return 0;
}
- 循环平移
取余的方法P49
- 字母出现次数统计
用一个number数组统计各个出现的概率
学会构造辅助数组
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
int num[128];//128个ASCII码
int main(){
string str1,str2;
while(getline(cin,str1)){
if(str1 == "#"){
break;
}
getline(cin,str2);
memset(num,0,sizeof(num));
for(int i=0;i<str2.size();i++){
num[str2[i]]++;
}
for(int i=0;i<str1.size();i++){
printf("%c %d\n",str1[i],num[str1[i]]);
}
}
return 0;
}
- int的范围
int有32位,2^32-1,注意int的范围使用
注意pow函数,需要头文件<math.h>,pow(2,n);
#include<iostream>
#include<string>
#include<algorithm>
#include<math.h>
using namespace std;
int main(){
string s;
while(cin>>s){
int sum=0;
for(int i=0;i<s.length();i++){
if(s[i]=='0')continue;
sum=sum+(s[i]-'0')*(pow(2,s.length()-i)-1);
}
cout<<sum<<endl;
}
}
- 首字母大写问题
复习:注意getline函数的使用(C语言可以用gets)
大写与小写字母的ASCII差值的使用
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main(){
string s;
int p;
while(getline(cin,s)){
if(s[0]>='a'&&s[0]<='z'){
p=s[0]+'A'-'a';
s[0]=p;
}
for(int i=1;i<s.size();i++){
if(s[i]==' '||s[i]=='\t'||s[i]=='\n'||s[i]=='\r'){
i=i+1;
if(s[i]>='a'&&s[i]<='z'){
p=s[i]+'A'-'a';
s[i]=p;
}
else{
i=i-1;
}
}
}
cout<<s;
}
}
字符串匹配
kmp算法
重点理解next数组的求法
#include<iostream>
#include<string>
#include<algorithm>
//KMP算法
using namespace std;
const int MAXM=10000;
const int MAXN=1000000;
int nextTable[MAXM];
int pattern[MAXM];
int text[MAXN];
//创建next表
void GetNextTable(int m){
int j=0;
nextTable[j]=-1;
int i=-1;
while(j<m){
if(i==-1||pattern[i]==pattern[j]){
i++;
j++;
nextTable[j]=i;
}else{
i=nextTable[i];
}
}
}
int main(){
return 0;
}
8 数据结构一
向量
vector
主要应用于不知道需要多大数组的方法
#include<vector>push_back()
pop_back()
empty()
size()
insert()
erase()
clear()
begin()
end()
#include<iostream>
#include<string>
#include<vector>
using namespace std;
vector<int>obj;
int main(){
for(int i=0;i<5;i++){
obj.push_back(i);
}
obj.insert(obj.begin(),3,15);
obj.pop_back();
for(int i=0;i<obj.size();i++){
cout<<obj[i]<<endl;
}
obj.erase(obj.begin()+5,obj.end());
vector<int>::iterator it;
for(it=obj.begin();it!=obj.end();it++){
cout<<*it<<" ";
}
obj.clear();
return 0;
}
https://www.nowcoder.com/practice/ccc3d1e78014486fb7eed3c50e05c99d?tpId=60&tqId=29492&tPage=1&ru=/kaoyan/retest/1001&qru=/ta/tsing-kaoyan/question-ranking求因数
#include<iostream>
#include<vector>
using namespace std;
int s(int x){
int sum=0;
for(int i=1;i<=x/2;i++){
if(x%i==0){
sum=sum+i;
}
}
//cout<<sum<<endl;
return sum;
}
int main(){
vector<int>obj1;
vector<int>obj2;
for(int i=2;i<=60;i++){
if(i==s(i)){
obj1.push_back(i);
}else if(i<s(i)){
obj2.push_back(i);
}
}
cout<<"E"<<":";
for(int i=0;i<obj1.size();i++){
cout<<" "<<obj1[i];
}
cout<<endl;
cout<<"G"<<":";
for(int i=0;i<obj2.size();i++){
cout<<" "<<obj2[i];
}
return 0;
}
队列
STL-queue
#include<queue>
queue<type>name
empty()
size()
push()
pop()
front()
back()
队头删除元素
队尾添加元素
队列应用约瑟夫问题
循环队列
案例
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
//模拟循环队列
int main(){
int n,p,m;
while(cin>>n>>p>>m){
if(n==0&&p==0&&m==0){
break;
}
queue<int>children;
for(int i=1;i<=n;i++){
children.push(i);//加入编号
}
for(int i=1;i<p;i++){
children.push(children.front());
children.pop();//把编号为p的放在第一位
}
while(!children.empty()){
for(int i=1;i<m;i++){//m-1个小孩重新入队
children.push(children.front());
children.pop();
}
if(children.size()==1){
cout<<children.front()<<endl;
}else{
cout<<children.front()<<',';
}
children.pop();
}
}
return 0;
}
栈
stack
stack<typename>name
empty()
size()
push()
back()
top()和队列不同的地方,只能访问栈顶
栈的应用
无法实现确定存放容器的大小
逆序输出
注意:int最大值:2^31-1=214748364(9位)
long long 最大值 2^64-1=9223372036854775807(19位)
#include<iostream>
#include<string>
#include<algorithm>
#include<stack>
using namespace std;
stack<long long>st;//用long long
int main(){
int n;
while(cin>>n){
for(int i=0;i<n;i++){
long long num;
cin>>num;
st.push(num);
}
while(!st.empty()){
cout<<st.top()<<" ";
st.pop();
}
cout<<endl;
}
return 0;
}
括号匹配
括号左右匹配
表达式求值
简单计算器
用栈解决
数据栈
符号栈
#include<iostream>
#include<algorithm>
#include<stack>
#include<string>
#include<iomanip>
using namespace std;
int pr(char c){//优先级顺序
if(c=='#'){
return 0;
}else if(c=='$'){
return 1;
}else if(c=='+'||c=='-'){
return 2;
}else{
return 3;
}
}
//取参与运算的数据
double getNumber(string s,int &index){
double number=0;
while(s[index]>='0'&&s[index]<='9'){
number=number*10+s[index]-'0';
index++;
}
return number;
cout<<1;
cout<<number<<endl;
}
//计算
double Calculate(double x,double y,char op){
double result=0;
if(op=='+'){
result=x+y;
}else if(op=='-'){
result=x-y;
}else if(op=='*'){
result=x*y;
}else if(op=='/'){
result=x/y;
}
return result;
}
int main(){
string str;
while(getline(cin,str)){
if(str=="0"){
break;
}
int index=0;//字符串处理定位
stack<double>data;//数据栈
stack<char>op;//运算符栈
str=str+'$';
op.push('#');
//cout<<str;
while(index<str.size()){
if(str[index]==' '){
index++;
}else if(str[index]>='0'&&str[index]<='9'){
data.push(getNumber(str,index));
//cout<<str;
//cout<<data.top();
//cout<<"zq";
}else{
if(pr(op.top())<pr(str[index])){
op.push(str[index]);
index++;
//cout<<str;
}else{
double y=data.top();//x和y顺序不能反
data.pop();
double x=data.top();
data.pop();
//cout<<str;
data.push(Calculate(x,y,op.top()));
op.pop();
//cout<<str;
}
}
}
//cout<<op.top();
cout<<fixed<<setprecision(2)<<data.top()<<endl;
}
return 0;
}
9 数学问题
进制转换
字符串的加减乘除
//author:Q_Zhang
#include<iostream>
#include<string>
#include<vector>
using namespace std;
string Divide(string str,int x){//字符串除法
int remainder=0; //余数
for(int i=0;i<str.size();i++){
int num=remainder*10+str[i]-'0';//每一步余数与下一位的组合
str[i]=num/x+'0';//除法运算
remainder=num%x;//在这一位的余数
}
int pos=0;
cout<<remainder<<endl;
while(str[pos]=='0'){//去除产生多余的0
pos++;
}
return str.substr(pos);
}
int main(){
string x;
cin>>x;
x=Divide(x,5);
cout<<x;
return 0;
}
最大公约数,最小公倍数
辗转相除法求最大公约数
两数乘积除以最大公约数即为最小公倍数
非递归
#include<iostream>
using namespace std;
int max(int a,int b){
int r;
if(a<b){
r=a;
a=b;
b=r;
}
r=a%b;
while(r!=0){
a=b;
b=r;
r=a%b;
}
return b;
}
int main(){
int m,n,result;
while(cin>>m>>n){
result=max(m,n);
cout<<result<<endl;
}
return 0;
}
递归很简单自行查阅质数
素数筛法
找到一个素数,就将它所有倍数均标记为非素数,则判定其为素数,并标记它的所有倍数为非素数,然后继续遍历
#include<iostream>
#include<vector>
using namespace std;
const int MAXN=10001;
vector<int>prime;
bool isPrime[MAXN];
void Init(){
for(int i=0;i<MAXN;i++){
isPrime[i]=true;
}
isPrime[0]=false;
isPrime[1]=false;
for(int i=2;i<MAXN;i++){
if(!isPrime[i]){
continue;
}
prime.push_back(i);
for(int j=i*i;j<MAXN;j=j+i){
isPrime[j]=false;
}
}
}
int main(){
Init();
int n;
bool output=false;
while(cin>>n){
for(int i=0;i<prime.size();i++){
if(prime[i]>=n){
break;
}
else if(prime[i]%10==1){
output=true;
cout<<prime[i]<<" ";
}
}
if(!output){
cout<<-1;
}
cout<<endl;
}
return 0;
}
质数判断
#include<iostream>
#include<cmath>
using namespace std;
bool Judge(int x){
if(x<2){
return false;
}
int bound=sqrt(x);
for(int i=2;i<=bound;i++){
if(x%i==0){
return false;
}
}
return true;
}
int main(){
int n;
bool s;
while(cin>>n){
s=Judge(n);
if(s){
cout<<"yes"<<endl;
}else{
cout<<"no"<<endl;
}
}
return 0;
}
分解质因数
、
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int main(){
int n;
while(cin>>n){
int num=0;
int bound=sqrt(n);
for(int i=2;i<=bound;i++){
while(n%i==0){
num++;
n=n/i;
}
}
if(n!=1)num++;//特别注意:如果n为质数的情况下
cout<<num<<endl;
}
return 0;
}
快速幂
核心思想:将指数化为2进制数,1对应的位是快速求幂的分解的指数
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int Fast(int a,int b,int mod){
int answer=1;
while(b!=0){ //核心思想:转化为2进制
if(b%2==1){
answer=answer*a;
answer=answer%mod;
}
b=b/2;
a=a*a;
a=a%mod;
}
return answer;
}
int main(){
int a,b;
while(cin>>a>>b){
if(a==0&&b==0){
break;
}
cout<<Fast(a,b,1000)<<endl;
}
return 0;
}
原理同快速幂,初始状态为单位矩阵
大整数的加减乘除 重要
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
void Switch(string &a,string &b){
string c=a;
a=b;
b=c;
}
int main(){
string a,b;
int len1,len2,p;
while(cin>>a>>b){
vector<int>obj;
len1=a.size();
len2=b.size();
if(len2<len1){
Switch(a, b);
}
int remain=0;
int i=a.size()-1;//特别注意:交换过后需要重新求解长度
int j=b.size()-1;
for(;i>=0;i--,j--){
p=a[i]-'0'+b[j]-'0'+remain;
if(p>=10){
remain=1;
p=p-10;
obj.push_back(p);
}else{
obj.push_back(p);
remain=0;
}
}
for(;j>=0;j--){
p=b[j]-'0'+remain;
if(p>=10){
remain=1;
p=p-10;
obj.push_back(p);
}else{
obj.push_back(p);
remain=0;
}
}
if(remain==1){
obj.push_back(1);
}
for(int k=obj.size()-1;k>=0;k--){
cout<<obj[k];
}
obj.clear();
cout<<endl;
}
return 0;
}
第二种思路:进位统一处理#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
void Switch(string &a,string &b){
string c=a;
a=b;
b=c;
}
int main(){
string a,b;
int len1,len2,p;
while(cin>>a>>b){
vector<int>obj;
len1=a.size();
len2=b.size();
if(len2<len1){
Switch(a, b);
}
int remain=0;
int i=a.size()-1;
int j=b.size()-1;
for(;i>=0;i--,j--){
p=a[i]-'0'+b[j]-'0'+remain;
if(p>=10){
remain=1;
p=p-10;
obj.push_back(p);
}else{
obj.push_back(p);
remain=0;
}
}
for(;j>=0;j--){
p=b[j]-'0'+remain;
if(p>=10){
remain=1;
p=p-10;
obj.push_back(p);
}else{
obj.push_back(p);
remain=0;
}
}
if(remain==1){
obj.push_back(1);
}
for(int k=obj.size()-1;k>=0;k--){
cout<<obj[k];
}
obj.clear();
cout<<endl;
}
return 0;
}
乘法稍微改一下就成#include<iostream>
#include<string>
using namespace std;
int main(){
string a,b;
int len1,len2,len3,i,j,k=0;
cin>>a;
cin>>b;
len1=a.length();
len2=b.length();
len3=len1+len2;
int aa[len1+1]={0},bb[len2+1]={0},cc[len3+1]={0};
for(i=1;i<=len1;i++){
aa[i]=a[len1-i]-'0';
}
for(i=1;i<=len2;i++){
bb[i]=b[len2-i]-'0';
}
for(i=1;i<=len1;i++){
for(j=1;j<=len2;j++){
cc[i+j-1]=cc[i+j-1]+aa[i]*bb[j]; //小技巧要注意
}
}
for(i=1;i<=len3;i++){
cc[i+1]=cc[i+1]+cc[i]/10;
cc[i]=cc[i]%10;
}
while(len3>0&&cc[len3]==0){
len3--;
}
if(len3==0){
cout<<0<<endl;
}
else{
for(i=len3;i>0;i--){
cout<<cc[i];
}
cout<<endl;
}
return 0;
}
10 贪心策略
最优时间分配:选择结束时间最早的
11 递归与分治
1.子问题要与原始问题相同
2.不能无限制调用本身,必须有个递归出口
阶乘可以用递归
汉诺塔
后期总结补充
分治法
斐波那契数列
#include<iostream>
#include<algorithm>
using namespace std;
int Fibonacci(int n){
if(n==1||n==0){
return n;
}else{
return Fibonacci(n-1)+Fibonacci(n-2);
}
}
int main(){
int n;
while(cin>>n){
cout<<Fibonacci(n)<<endl;
}
}
子树有多少个节点问题
12 搜索(难度较大,掌握后level上升一个台阶)
广度优先搜索BFS
需要有访问标记
玛雅密码
深度优先搜索DFS
八皇后问题
13 数据结构二
二叉树的遍历
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
struct TreeNode{
int data;
TreeNode *leftChild;
TreeNode *rightChild;
};
//前序遍历
void PreOrder(TreeNode *root){
if(root==NULL){
return;
}
cout<<root->data;
PreOrder(root->leftChild);
PreOrder(root->rightChild);
return;
}
//中序遍历
void InOrder(TreeNode *root){
if(root==NULL){
return;
}
InOrder(root->leftChild);
cout<<root->data;
InOrder(root->rightChild);
return;
}
//后序遍历
void PostOrder(TreeNode *root){
if(root==NULL){
return;
}
PostOrder(root->leftChild);
PostOrder(root->rightChild);
cout<<root->data;
return;
}
//层序遍历
void LevelOrder(TreeNode *root){
queue<TreeNode *>myQueue;
if(root!=NULL){
myQueue.push(root);
}
while(!myQueue.empty()){
TreeNode *current=myQueue.front();
myQueue.pop();
cout<<current->data;
if(current->leftChild!=NULL){
myQueue.push(current->leftChild);
}
if(current->rightChild!=NULL){
myQueue.push(current->rightChild);
}
}
return;
}
int main(){
return 0;
}
通过先序遍历和中序遍历构建树
https://www.nowcoder.com/questionTerminal/6e732a9632bc4d12b442469aed7fe9ce(未理解)
#include<iostream>
#include<algorithm>
using namespace std;
struct TreeNode{
char data;
TreeNode *leftChild;
TreeNode *rightChild;
TreeNode(char c): data(c),leftChild(NULL),rightChild(NULL){}
};
TreeNode *Build(string str1,string str2){
if(str1.size()==0){
return NULL;
}
char c = str1[0];
TreeNode *root=new TreeNode(c);
int posion=str2.find(c);
root->leftChild=Build(str1.substr(1,posion),str2.substr(0,posion));
root->rightChild=Build(str1.substr(posion+1), str2.substr(posion+1));
return root;
}
void PostOrder(TreeNode *root){
if(root==NULL){
return;
}
PostOrder(root->leftChild);
PostOrder(root->rightChild);
cout<<root->data;
return;
}
int main(){
string str1,str2;
while(cin>>str1>>str2){
TreeNode *root = Build(str1,str2);
PostOrder(root);
cout<<endl;
}
return 0;
}
二叉排序树
https://www.nowcoder.com/practice/30a0153649304645935c949df7599602?tpId=69&tqId=29654&tPage=1&ru=/kaoyan/retest/11002&qru=/ta/hust-kaoyan/question-ranking
(weilijie)
#include<iostream>
#include<algorithm>
using namespace std;
struct TreeNode{
int data;
TreeNode *leftNode;
TreeNode *rightNode;
TreeNode(int x): data(x),leftNode(NULL),rightNode(NULL){}
};
TreeNode *Insert(TreeNode *root,int x,int father){
if(root==NULL){
root=new TreeNode(x);
cout<<father<<endl;
}else if(x<root->data){
root->leftNode=Insert(root->leftNode,x,root->data);
}else{
root->rightNode=Insert(root->rightNode,x,root->data);
}
return root;
}
int main(){
int n;
while(cin>>n){
TreeNode *root=NULL;
for(int i=0;i<n;i++){
int x;
cin>>x;
root=Insert(root,x,-1);
}
}
return 0;
return 0;
}
优先队列
#include<queue>
优先队列的典型应用:
priority_queue<int>myQueue;
默认是大顶堆
哈夫曼树
哈夫曼树需要改为小顶堆,用greater
priority_queue<int,vector<int>,greater<int>>myQueue;
#include<iostream>
#include<queue>
using namespace std;
int main(){
int n;
while(cin>>n){
priority_queue<int,vector<int>,greater<int>>myQueue;
while(n--){
int x;
cin>>x;
myQueue.push(x);
}
int result=0;
while(myQueue.size()>1){
int p=myQueue.top();
myQueue.pop();
int q=myQueue.top();
myQueue.pop();
result=result+p+q;
myQueue.push(p+q);
}
cout<<result<<endl;
}
return 0;
}
散列表
#include<map> map<int,int>name; map.empty() map.size() map.insert(); map.erase(); [] at() find() clear() begin() end()
散列表操作
#include<iostream>
#include<map>
#include<string>
using namespace std;
map<string,int>myMap;
int main(){
myMap["em"]=67;
myMap.insert(pair<string,int>("bob",72));
cout<<myMap.size()<<endl;
cout<<myMap["bob"]<<endl;
cout<<myMap.at("em")<<endl;
myMap.erase("em");
map<string,int>::iterator it;
for(it = myMap.begin();it!=myMap.end();it++){
cout<<it->first<<' '<<it->second<<endl;
}
myMap.clear();
it=myMap.find("bob");
if(it==myMap.end()){
cout<<"没找到";
}
return 0;
}
字串计算
注意substr()的使用
#include<iostream>
#include<map>
#include<string>
using namespace std;
int main(){
string str;
while(cin>>str){
map<string,int>count;
for(int i=0;i<=str.size();i++){
for(int j=0;j<i;j++){
string key=str.substr(j,i-j);
count[key]++;
}
}
map<string,int>::iterator it;
for(it=count.begin();it!=count.end();it++){
if(it->second>1){
cout<<it->first<<" "<<it->second<<endl;
}
}
}
return 0;
}
14 图论(really difficult)学会再提升一个level
最小生成树
最短路径 迪杰斯特拉算法
拓扑排序
关键路径
后续更新
(水平有限)
15 动态规划
斐波那契额数列的变体
上楼梯问题
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 92;
long long dp[MAXN];
int main(){
dp[0]=0;
dp[1]=1;
for(int i=2;i<MAXN;i++){
dp[i]=dp[i-1]+dp[i-2];
}
int n;
while(cin>>n){
cout<<dp[n+1]<<endl;
}
return 0;
}
最大连续子序列和
https://www.nowcoder.com/questionTerminal/df219d60a7af4171a981ef56bd597f7b#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=1000000;
long long arr[MAXN];
long long dp[MAXN];
long long Max(int n){
long long maxs=0;
for(int i=0;i<n;i++){
if(i==0){
dp[i]=arr[i];
}else{
dp[i]=max(arr[i],dp[i-1]+arr[i]);
}
maxs=max(maxs,dp[i]);
}
return maxs;
}
int main(){
int n;
while(cin>>n){
for(int i=0;i<n;i++){
cin>>arr[i];
}
long long answer=Max(n);
cout<<answer<<endl;
}
return 0;
}
二维:
https://www.nowcoder.com/practice/1c5fd2e69e534cdcaba17083a5c56335?tpId=61&tqId=29506&tPage=1&ru=/kaoyan/retest/1002&qru=/ta/pku-kaoyan/question-ranking最长递增子序列
设置一个dp[ ]表示以A[ i ]作为末尾的最长递归子序列长度,则最长递增子序列长度是dp[ ]数组中的最大值
两种情况:
A[i]之前的元素都比她大,则dp[ i ]=1;
之前的元素比它小
#include<iostream>
using namespace std;
const int MAXN=1000;
int arr[MAXN];
int dp[MAXN];
int main(){
int n;
while(cin>>n){
for(int i=0;i<n;i++){
cin>>arr[i];
}
int answer=0;
for(int i=0;i<n;i++){
dp[i]=arr[i];
for(int j=0;j<i;j++){
if(arr[j]<arr[i]){
dp[i]=max(dp[i],dp[j]+arr[i]);
}
}
answer=max(answer,dp[i]);
}
cout<<answer<<endl;
}
return 0;
}
最长公共子序列
dp[ i ] [ j ]表示以S1[i]和S2[j]作为末尾的最长公共子序列长度
s1[i]==s2[j] dp[i][j]=dp[i-1][j-1]+1; s1[i]!=s2[j] dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN=1001;
char s1[MAXN];
char s2[MAXN];
int dp[MAXN][MAXN];
int main(){
while(scanf("%s%s",s1+1,s2+1)!=EOF){
int n=strlen(s1+1);
int m=strlen(s2+1);
for(int i=0;i<=n;i++){
for(int j=0;j<=m;j++){
if(i==0||j==0){
dp[i][j]=0;
continue;
}
if(s1[i]==s2[j]){
dp[i][j]=dp[i-1][j-1]+1;
}else{
dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
}
}
}
cout<<dp[n][m];
}
return 0;
}
背包问题
0-1背包
(未理解)欢迎交流
(记住)
#include<iostream>
using namespace std;
const int MAXN=1001;
int v[MAXN];//价值
int w[MAXN];//重量
int dp[MAXN];
int main(){
int n,m;
while(cin>>m>>n){
for(int i=0;i<n;i++){
cin>>w[i]>>v[i];
}
for(int i=0;i<=m;i++){//初始化
dp[i]=0;
}
for(int i=0;i<n;i++){
for(int j=m;j>=w[i];j--){ //特别注意要逆序遍历
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
}
}
cout<<dp[m]<<endl;
}
return 0;
}
完全背包
与0-1背包不同,每种物品可以取不止一件
(未理解)
只需将0-1背包的逆向改为正向即可
其他问题
整数拆分
#include<iostream>
using namespace std;
const int MAXN=1000001;
int dp[MAXN];
int main(){
dp[0]=1;
dp[1]=1;
for(int i=2;i<=MAXN;i++){
if(i%2==0){
dp[i]=(dp[i-1]+dp[i/2])%1000000000;
}
else{
dp[i]=dp[i-1];
}
}
int n;
while(cin>>n){
cout<<dp[n]<<endl;
}
return 0;
}
2020-9-6于南京NUIST
转载请标明出处

浙公网安备 33010602011771号