复试上机练习

复试

nbuoj+洛谷基础算法题

1224 哥德巴赫猜想(2)

题目描述
所谓哥德巴赫猜想,就是指任何一个大于2的偶数,都可以写成两个素数的和。现在输入一个偶数,要求寻找两个素数,使其和等于该偶数。由于可能有多组素数对满足条件,所以本题要求输出两数差最小的那两个素数。
注意 / 和% 的区别
以及函数调用求素数

#include<iostream>
using namespace std;
int issu(int a){
	int res=1;
	for(int i=2;i<a-1;i++){
		if(a%i==0){
			res=0;
			break;
		}
	}
	return res;
}
int main(){
	int n;
	cin>>n;
	int h=n/2;
	for(int i=h;i>1;i--){
		if(issu(i)&&issu(n-i)){
			cout<<i<<" "<<n-i<<endl;
			return 0;
		}
	}
}

1171 多个数的最小公倍数

题目描述
也许你已经会了求2个数字最小公倍数的方法,但是如果求多个数字的最小公倍数,你又能找到办法吗?
使用set标记break节省时间

#include<iostream>
using namespace std;
int main(){
	int n;
	int a[101];
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	for(int i=1;;i++){
		int set=1;//是 
		for(int j=0;j<n;j++){
			if(i%a[j]!=0){
				set=0;//不是 
				break;
			}
		}
		if(set==1){
			cout<<i<<endl;
			break;
		}
	}
}

1188 数字移位

题目描述
有n个整数,要求将前面各数字顺序向后移动m个位置,并将最后面的m个数变成最前面m个数。

#include<bits/stdc++.h>
using namespace std;
void reverse(int a[],int l,int r){
	int temp=0;
	int mid=(r-l+1)/2; //中间位置 
	for(int i=0;i<mid;i++){
		temp=a[i+l];
		a[i+l]=a[r-i];
		a[r-i]=temp;
	}
}
int main(){
	int n=0,m=0;
	int a[101];
	cin>>n>>m;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	reverse(a,0,n-1);
	reverse(a,0,m-1);
	reverse(a,m,n-1);
	for(int i=0;i<n-1;i++){
		cout<<a[i]<<" ";
	}
	cout<<a[n-1]<<endl;
}

1195 巧妙推算走楼梯

题目描述
有一楼梯共M级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第M级,共有多少种走法?
后面数据以前面为基础进行、使用相同算法

#include<iostream>
using namespace std;
int a[45]={0};

int main(){
	int n;
	int m;
	cin>>n;
	a[0]=0;
	a[1]=1;
	a[2]=1;
	a[3]=2;
	for(int i=4;i<42;i++){
		a[i]=a[i-1]+a[i-2];
	}
	for(int i=0;i<n;i++){
		cin>>m;
		cout<<a[m]<<endl;
	}
} 

P1115 最大子段和(动态规划)

给出一个长度为 n 的序列 a,选出其中连续且非空的一段使得这段和最大。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n[200001],p,ans[200001]={0};
    int sum=-9999999;//|x|<=10000   QWQ
    cin>>p;
    for(int i=1;i<=p;i++)
    {
        cin>>n[i];//输入
        ans[i]=max(ans[i-1]+n[i],n[i]);//DP
        sum=max(sum,ans[i]);//取最大值也同时进行,节约时间
    }
    cout<<sum;//直接输出
    return 0;
}

P1873 砍树(二分查找)未完成

P1223 排队接水(贪心最简单)

在这里插入图片描述
输出序号可以用结构体方式

那么针对这两个元素:就有两种排列情况:

1.ai排在bi前面那么有总时间:t1=ai+ai+bi.

2.bi排在ai前面那么有总时间:t2=bi+bi+ai.

##于是由ai<bi得出 t1<t2—》变一下式子—》ai+ai+bi<bi+bi+ai;

再化简不等式得出ai<bi

于是得出结论:当ai在bi前面时,时间为最小值。

于是反推回总体,两两相较,那么越小的应该越排在前面,以至于总时间越小

P1090 合并果子(贪心)(STL)

在这里插入图片描述
STL优先队列

#include<iostream>
#include<queue>
using namespace std;
priority_queue< int,vector<int>,greater<int> >q;
//注意格式 !空格 pop出最小的那个
int main(){
	int n;
	int a;
	int sum=0;
	cin>>n;
	while(n--){
		cin>>a;
		q.push(a);
	}
	while(q.size()>=2){
		int a=q.top();
		q.pop();
		int b=q.top();
		q.pop();
		q.push(a+b);
		sum+=a+b;
	}
	cout<<sum;
}

自定义

#include<queue>
struct Node{
    int x,y;
    Node(int a=0, int b=0):
        x(a), y(b) {}
};
 
struct cmp{
    bool operator()(Node a, Node b){
        if(a.x == b.x)    return a.y>b.y;
        return a.x>b.x;
    }
};
    priority_queue<Node, vector<Node>, cmp>p;

P1219 八皇后(搜索深搜+回溯)

在这里插入图片描述
注意for循环从1开始

#include<iostream>
using namespace std;
int ans[14];//结果 
int check[3][28]={0};//列,左右斜线
int sum=0;
int n;
void eq(int line){
	if(line>n){
		sum++; 
		if(sum>3)return;
		else
		{
			for(int i=1;i<=n;i++)
				cout<<ans[i]<<" ";
			cout<<endl;
			return;
		} 	
	}
	for(int i=1;i<=n;i++){//列遍历 有无  两斜线有无 
		if((!check[0][i])&&(!check[1][i+line])&&(!check[2][line-i+n])){
		//规律
			ans[line]=i;
			check[0][i]=1;check[1][i+line]=1;check[2][line-i+n]=1;
			eq(line+1);//回溯搜索下一行 
			check[0][i]=0;check[1][i+line]=0;check[2][line-i+n]=0;
			//复原 
		}
	}
} 
int main(){
	cin>>n;
	eq(1);//行 
	cout<<sum;
	return 0;
}

P1443 马的遍历(搜索广度优先队列)

#include<bits/stdc++.h>
#define re(i,a,b) for(int i=(a);i<=(b);i++) 
using namespace std;
struct A{
	int x,y,cnt;
};
int mp[401][401];
bool vis[401][401];
//int xx[]={1,1,-1,-1,2,2,-2,-2};
//int yy[]={2,-2,2,-2,1,-1,-1,1};
int xx[]={1,2,-1,-2,1,2,-1,-2};
int yy[]={2,1,2,1,-2,-1,-2,-1};
int main(){
	re(i,1,400)
	re(j,1,400)
	mp[i][j]=-1;
	int x1,y1,m,n;
	cin>>m>>n>>x1>>y1;
	queue<A>q;
	q.push(A{x1,y1,0});
	vis[x1][y1]=1;//存入即遍历到 
	mp[x1][y1]=0;
	while(!q.empty()){
		for(int i=0;i<8;i++){
			int dx=xx[i]+q.front().x;
			int dy=yy[i]+q.front().y;
			if(dx>=1&&dx<=m&&dy>=1&&dy<=n&&vis[dx][dy]==0){
				q.push(A{dx,dy,q.front().cnt+1});
				vis[dx][dy]=1;
				mp[dx][dy]=q.front().cnt+1;
			}
		}
		q.pop();//用完后出队列 
	}
	re(i,1,m){
		re(j,1,n){
			//cout<<mp[i][j]<<" ";	
			printf("%-5d",mp[i][j]); 
		}
		cout<<endl;
	}
	return 0;
}

P1259 黑白棋子的移动(递归)

#include<iostream>
using namespace std;
int n,st,sp;
char c[101];
void print()                                  //打印
{
	int i;
	cout<<"step "<<st<<':';
	for (i=1;i<=2*n+2;i++) cout<<c[i];
	cout<<endl;
	st++;
}
void init(int n)                             //初始化
{
	int i;
	st=0;
	sp=2*n+1;
	for (i=1;i<=n;i++) c[i]='o';
	for (i=n+1;i<=2*n;i++) c[i]='*';
	c[2*n+1]='-';c[2*n+2]='-';
	print();
}
void move(int k)                            //移动一步
{
	int j;
	for (j=0;j<=1;j++) 
	{
	   c[sp+j]=c[k+j];
	   c[k+j]='-';
	}
	sp=k;//上个空位 
	print();
}
void mv(int n)                                       //主要过程
{
	int i,k;
	if (n==4)                //n等于4的情况要特殊处理
	{
		move(4); move(8); move(2); move(7); move(1);
		}
	else
	{
		move(n); move(2*n-1); mv(n-1);
	}
}
int main()
{
	cin>>n;
	init(n);
	mv(n);
}

P1969 积木大赛(实验7)

F1规律

#include <iostream>
using namespace std;
int main()
{
    int n,a,last=0,ans=0;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a;
        if(a>last)ans+=(a-last);
        cout<<ans<<" "; 
        last=a;
        cout<<last<<endl;
    }
    cout<<ans<<endl;
}

P1318 积水面积(c++?)

import java.util.Scanner;
import java.util.Stack;
class A{
    A(int h,int i){
        height =h;
        index=i;
    }
    int height;
    int index;
}
public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int n,res=0;
        Stack<A>s=new Stack<A>();
        A a= new A(0,0);
        s.push(a);
        Scanner scan=new Scanner(System.in);
        n=scan.nextInt();
        for(int i=1;i<=n;i++){
            A top=s.peek();
            a=new A(scan.nextInt(),i);
            while(s.size()>1&&top.height<a.height){//有积水
                int h=top.height;
                s.pop();
                top=s.peek();
                int w = a.index-top.index-1;
                if(a.height>top.height)h=top.height-h;
                else h=a.height-h;
                res+=w*h;
                //System.out.println(w+" "+h);

            }
            if(a.height>=top.height)s.pop();
            s.push(a);
        }
        System.out.println(res);
    }

}

P1048 采药(实验8 )🧡

01背包问题
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int m,t;
int dp[1005];
int c;//时间
int v;//价值
int main(){
	cin>>t>>m;
	for(int i=1;i<=m;i++){//物品序号 
		cin>>c>>v;//和上一个物品没有关联 
		for(int j=t;j>=c;j--){//时间 
			dp[j]=max(dp[j-c]+v,dp[j]);
			//倒退 有这个或没有
		}
	}
	cout<<dp[t];
	return 0;
} 

P1095 守望者的逃离(未完成)

现在已知守望者的魔法初值M,他所在的初始位置与岛的出口之间的距离S,岛沉没的时间T。你的
任务是写一一个程序帮助守望者计算如何在最短的时间内逃离荒岛,若不能逃出,则输出守望者在剩下的
时间内能走的最远距离。
CSDN

#include<cstdio> 
#include<cstring>
#include<iostream> 
#include<algorithm>
#include<cmath>
using namespace std;
int main()
{
    int m,s,t,now=0;
    cin>>m>>s>>t;
    int s1=0,s2=0;//存放跑步能走的距离和用闪烁能走的距离
    for(int i=1;i<=t;i++)//一个个时间去推
    {
        s1+=17;//闪现和跑步分批进行
        if(m>=10) {s2+=60;m-=10;}//能够闪现这肯定要闪现的,
        else m+=4;//没蓝这一回合就用来回蓝
        if(s2>s1) s1=s2;//闪现的快了就把跑步的替换成闪现的
        if(s1>s){//跑出去了就输出当前时间
            cout<<"Yes"<<endl<<i<<endl;
            return 0;
        }
    }
    cout<<"No"<<endl<<s1<<endl;//时间都用完了还没跑出去,输出“No”和s1的值,(由于闪现可走距离一旦大于跑步的跑步的距离就会被替换,这时跑的距离远的一定是s1)
}

P1020 导弹拦截

P1021 邮票面值设计(参考答案)

#include<iostream>
#include<cstring>//头文件
using namespace std;
int a[17],n,k,ans[17],maxn;//a【】表示这种方法的邮票,ans【】表示如今取得的解即要输出的
int dp(int t,int mx){
    int f[50000];//f[i]为拼i所需的最少数的个数
    f[0]=0;//边界
    for(int i=1;i<=a[t]*n;i++)
      f[i]=50000;//赋初值赋一个尽可能地大就可以了
    for(int i=1;i<=t;i++)            //从第一位找到目前的位数把所有已找的邮票都枚举 
      for(int j=a[i];j<=a[t]*n;j++)   //因为不可能找到比自己小的数,所以从自己开始找 
        f[j]=min(f[j],f[j-a[i]]+1);    //比较上几次已找到的最小需要位数和即将要找的相比较,取较小值 
for(int i=1;i<=a[t]*n;i++)
      if(f[i]>n)//如果所需最小的个数大于n就意味着这种情况不符合,但f【i-1】是符合的不然f【i-1】就会判断所以不符合返回i-1
        return i-1;
    return a[t]*n;//如果到a【t】*n的f【i】都满足意味着能取到的最大连续数就是a【t】*n
}
void dfs(int t,int mx){              // 为什么全部找完:因为多几张邮票肯定比少几张邮票可能的情况多,所以全部找完是最好的  
    if(t==k+1){        //如果所有邮票数已经找完,那么就和 maxn比较谁更大   
        if(mx>maxn){
            maxn=mx;
            for(int i=1;i<=t-1;i++)
              ans[i]=a[i];} //保存所需要的邮票面值  
        return;
        }
    for(int i=a[t-1]+1;i<=mx+1;i++){  //继续找:为了避免重复,下一张邮票要比上一张邮票大,所以上边界是a[t-1]+1,同时它不能比最大连续值+1还大,不然最大连续值的下一个数就永远连不起来了 
      a[t]=i;
      int x=dp(t,mx);   //动归寻找此时的最大连续数 
      dfs(t+1,x);
    }
}
int main(){
    cin>>n>>k;
    dfs(1,0);  //先从第一张开始找,第一张前面没有数,所以所连续的最大数为 0 
    for(int i=1;i<=k;i++)//输出 注意打空格以及大写换行即可
      cout<<ans[i]<<" ";
    cout<<endl;
    cout<<"MAX="<<maxn<<endl;
    return 0;
}

抓码每日一题(字符串)

链接

部分A+B

正整数A的“DA(为1位整数)部分”定义为由A中所有DA组成的新整数PA。例如:给定A = 3862767,DA= 6,则A的“6部分”PA是66,因为A中有2个6。
现给定A、DA、B、DB,请编写程序计算PA + PB。
字符串和数字转化注意 - ‘0’

//输出样例1:
//3862767 6 13530293 3
//输出样例2:
//399
#include<iostream>
using namespace std;
string a,b;
int da,db;
int main(){
	int cnta = 0;
	int cntb = 0;
	int pa = 0;
	int pb = 0;
	cin>>a>>da>>b>>db;
	for(int i=0;i<a.length();i++){ 
		if(da==a[i]-'0'){//
			cnta++;
		}
	}
	for(int i=0;i<b.length();i++){
		if(db==b[i]-'0'){
			cntb++;
		}
	}
	while(cnta--){
		pa=pa*10+da;
	}
	while(cntb--){
		pb=pb*10+db;
	}
	cout<<pa+pb;
} 

组个最⼩数

注意思想输出最小的数

//输出样例:
//2 2 0 0 0 3 0 0 1 0
//输出样例:
//10015558
//最小数 
#include<iostream>
using namespace std;
int a[10]={0};
int main(){
	for(int i=0;i<10;i++){
		cin>>a[i];
	}
	//首先输出第一个不为0
	for(int i=1;i<10;i++){
		if(a[i]!=0){
			cout<<i;
			a[i]--;
			break;
		}
	}
	for(int i=0;i<a[0];i++){
		cout<<0;
	} 
	for(int i=1;i<10;i++){
		while(a[i]--){
			cout<<i;
		}
	}
	return 0;
}

4翻转链表

#include<iostream>
#include<algorithm>
/*
测试用例 
00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

输出结果 
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1
*/
using namespace std;
int first, k, n, temp; 
int data[100005], next[100005], list[100005];
//数值列表  下一节点列表   顺序列表 
int main(){
	cin>>first>>k>>n;
	for(int i=1;i<n;i++){
		cin>>temp;
		cin>>data[temp]>>next[temp];
	}
	int sum = 0;
	while(first!=-1){
		list[sum++] = first;//list 0 = 地址 
		first = next[first];//下一地址 
	}
	
	for(int i=0;i<(sum -= sum%k);i+=k)
		reverse(list + i,list+i+k);
	for(int i=0;i<sum-1;i++){
		printf("%05d %d %05d\n",list[i],data[list[i]],list[i+1]);
	}
	printf("%05d %d -1\n",list[sum-1],data[list[sum-1]]);
}

5打印沙漏(找规律a)

*****
 ***
 *
***
*****

假设扩展的层数为 i,则扩展出去的上边需要的所有符号个数为3 + 5 + 7 + …+ (2i+1) = (3 + 2i + 1) * i / 2 = i * (i + 2),扩展出去的下边与上边同样多所以乘以2,加上最重要那⼀⾏1个符号,所以 总共需要2 * i * (i + 2) + 1个符号,所以i从0到N,找满⾜(2 * i * (i + 2) + 1)> N的最小的 i。

6旧的键盘

toupper
string::npos

int main(){
	string s1,s2;
	cin>>s1>>s2;
	string ans="";
	for(int i=0;i<s1.length();i++){
		if(s2.find(s1[i]) == string::npos &&ans.find(toupper(s1[i])) == string::npos){
			ans+=toupper(s1[i]);
		} 
	}
	cout<<ans;
}
t = N / 2 + N % 2,表示偶数等于除以2,
奇数要除以2加1的意思,这样才能满⾜四舍五⼊。

11有几个PAT

注意思想,每次遇到A统计一次。

要想知道构成多少个PAT,那么遍历字符串后对于每⼀A,
它前⾯的P的个数和它后⾯的T的个数的乘积就是能构成的PAT的个数。
然后把对于每⼀个A的结果相加即可。
只需要先遍历字符串数⼀数有多少个T,然后每遇到⼀个T,countt–;
每遇到⼀个P,countp++;然后⼀遇到字⺟A就countt * countp。
#include <iostream>
#include <vector>
using namespace std;
int main() {
	string s;
	cin>>s;
	int len = s.length();
	int ans = 0,coutp=0,coutt=0	;
	for(int i=0;i<len;i++){
		if(s[i]=='T'){
			coutt++;
		}
	}//先统计T个数 
	for(int i=0;i<len;i++){
		if(s[i]=='T')coutt--;
		if(s[i]=='P')coutp++;
		if(s[i]=='A')ans= (ans+(coutp*coutt)%10000000007)%10000000007;
	}
	cout<<ans;
    return 0; 
}

29数字加密

本题要求实现⼀种数字加密⽅法。⾸先固定⼀个加密⽤正整数A,对任⼀正整数B,将其每1位数字与A的对应位置上的数字进⾏以下运算:对奇数位,对应位的数字相加后对13取余——
这⾥⽤J代表10、Q代表11、K代表12;

输⼊样例:
1234567 368782971
输出样例:
3695Q8118

字符串逆置加减处理

#include<iostream>
#include<algorithm>
using namespace std;
int main(){
	string a,b,c;
	cin >> a >> b;
	int lena = a.length(),lenb = b.length();
	reverse(a.begin(),a.end());//逆置后 
	reverse(b.begin(),b.end());
	if(lena > lenb){//补0 
		b.append(lena - lenb ,'0');
	}
 	if(lenb > lena){
		a.append(lenb - lena ,'0');
	}
	char str[14] = {"0123456789JQK"};
	//数组! 
	for(int i=0;i<a.length();i++){
		if(i%2==0){//奇数 
			c+=str[(a[i]- '0' + b[i] - '0')%13];
		}else{
			int temp = b[i]-a[i];
			if(temp<0){
				temp = temp+10;	
			}
			c += str[temp];
		}
	} 
	cout<<c.length();
	for(int i= c.length()-1;i>=0;i--){
		cout<<c[i];1234567 368782971	
	}
	return 0;
}

王道上机书

1暴力

枚举
反序数+注意初试化

#include<iostream>
using namespace std;
int rev(int x){
	int re=0;//注意初始化为0!!! 
	while(x!=0){
		re*=10;
		re += x%10;
		x/=10;
	}
	return re;
}

int main(){
	for(int i =1000;i<=9999;i++){
		if(i*9 == rev(i)){
			cout<<i<<endl;
		}
	}
}

模拟
画图:模拟数组
寻找规律啊
题目:Hello World for U#

n2随长度增加呈现出一个有规律的数列,3个一组
从最短长度5开始,n2为:3,4,3,4,5,4,5,6,5,6,7,6,7,8,7,8,9,8,9,10......
int suren2(int len){//计算n2
    if(len%3==0||len%3==2) return len/3+2;
    else return len/3+1;
}

日期问题

#include<iostream>
using namespace std;
//日期问题 
int year,month,day;
int ans=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}
};
bool isLeapyear(int year){//4 并且 100  或400 
	return (year%4==0&&year%100==0)||(year%400==0);
} 
int main(){
	while(scanf("%d%d%d",&year,&month,&day) != EOF){
	//循环输入!!!
		for(int i=1;i<month;i++){
			ans+=daytab[isLeapyear(year)][i]; 
		}
			ans+=day;
			cout<<ans;
	}
}

其它模拟
区间除树问题:最后可以不用遍历,当为1变false,数量–;
手机键盘:注意建立模拟记录数组,keytable【】

输入
scanf
%c 读入一个字符
%d 读入十进制整数
%s 读入一个字符串,遇空格、制表符或换行符结束。
输出
yyyy-mm-dd形式可能有0格式凑0
printf("%04d-%02d-%02d\n",year,month,day);

2二分查找

KY199 查找

#include<iostream>
#include<algorithm>
using namespace std;
int n, m;
const int MAXN = 1000;
int a[MAXN];
bool BinarySearch(int target, int n) {
    int l = 0;
    int r = n;
    while (l <= r) {
        int middle = (l + r) / 2;
        if (a[middle] < target) {
            l =  middle + 1;
        } else if (a[middle] > target) {
            r = middle - 1;
        } else {
            return true;
        }
    }
    return false;
}
int main() {
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    sort(a, a + n);
    cin >> m; //查找个数
    for (int i = 0; i < m; i++) {
        int t;
        cin >> t;
        if (BinarySearch(t, n)) {
            cout << "YES" << endl;
        } else cout << "NO" << endl;
    }
    return 0;
}
/*
4
9 8 17 6
*/

3字符串相关知识

s.find()//返回查找位置
if(t.find("ewq")==string::npos){
		cout<<"nofind";//未查找到为string::nops
}
	
cout<<t.substr(1,3);//截取字符串(开始,个数)

string str;
getline(cin,str);
cout<<str;//getline可以不考虑空格

//'a''z'相差25
cout<<'A'-'a'; //-32

str[i] = (str[i]-'A'-5+26)%26+'A';
//加减循环算法,+26%26可以抵消不用分情况

KY127 统计字符(字符存储)

#include <iostream>
#include <algorithm>
using namespace std;
string str1,str2;
int number[128];
int main()
{
	while(getline(cin,str1)){
		if(str1=="#"){
			break;
		}
		getline(cin,str2);
		for(int i=0;i<128;i++)number[i]=0;//注意清0 
		for(int i=0;i<str2.length();i++){
				number[str2[i]]++;			
		}
		for(int i=0;i<str1.length();i++){
			cout<<str1[i]<<" "<<number[str1[i]]<<endl;
		}
	}
}
/*
I
THIS IS A TEST
i ng
this is a long test string
#

I 2
i 3
  5
n 2
g 2

*/ 

23复试:延迟的回文数

字符串相加算法,高精度

#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
/*
97152

97152 + 25179 = 122331
122331 + 133221 = 255552
255552 is a palindromic number.
*/
string rev(string t){//翻转 
	reverse(t.begin(),t.end());
	return t;
}
//高精度
string add(string s1,string s2){
	string s = s1;
	int carry=0;
	for(int i = s1.length()-1; i>=0; i--){
		s[i] = (s1[i]-'0' + s2[i] - '0' + carry) % 10 + '0';
		carry = (s1[i]-'0' +  s2[i]-'0' + carry)/10;
	} 
	
	if(carry > 0 )s = "1"+s ;//向前进位 
	return s; 
}

int main(){
	string t;
	cin>>t;
	int cnt=10;
	
	if(t == rev(t)){
		cout<<"yes";
		cout<<t;
	}
	
	while(cnt--){
		
		string temp = t;
		if(rev(t)==temp){//成功 
			cout<<t<<"yes"<<endl;//输出 
			return 0;
		}
		
		cout<<t<<"+"<<rev(t)<<endl;
		t = add(temp,rev(t)); 
		//超过10次 
	}
	cout<<"Not found in 10 iterations"<<endl;
} 

23复试:互评成绩计算

#include <iostream>
#include <algorithm>
using namespace std;
/*
互评成绩计算
 
*/
int main(){
	int n,m;
	cin>>n>>m;
	for(int i= 0;i<n;i++){
		int cnt = -2;
		int g1=0,g2=0,temp,maxn = -1,minn = m+1;
		cin>>g1;
		for(int i=1;i<n;i++){
			cin>>temp;
			if(temp>=0&&temp<=m){
				if(temp > maxn) maxn = temp;
				if(temp < minn) minn = temp;
				cnt++;//计合规分数 
				g2+=temp;//分组加分 
			}
		}
	 	cout << int((((g2-maxn-minn)* 1.0 / cnt) + g1) / 2 + 0.5) << endl;
	 //舍四进五 + 0.5int() 
	} 
}

字符串KMP(待完成)

4贪心

例题🧡
01背包
部分包
购买贺年卡.
硬币问题
删数问题
拦截导弹问题添加链接描述
排队接水
均分纸牌

senior‘s gun

	for(int i=0;i<n;i++){
		if((i>=m)&&gun[i]>=monstor[i]){
			//还有怪物射杀并且可以杀死怪物 
			break; 
		}
		ans+=(gun[i]-monstor[i]);
	}

KY4 代理服务器(未完成)
其实就是想要尽可能使用和要访问服务器没有交集的代理服务器。
如果要访问的服务器中没有和代理服务器 IP 相同的,返回 0
如果有相同的,那么每个代理服务器都在某一个位置相同,比如例子中的分别在 1、4、2 处相同,那么贪心策略取最远相同的,然后对剩下的再次进行判断即可。
因为服务器 IP 没有说明是否不重复,所以一个代理服务器 IP 可能在多个位置与要访问的服务器 IP 相同,所以取最远的位置其实是第一次相同时的最远位置。然后更新遍历 sever 的起始地址,直到遍历完全。

#include<iostream>
#include<vector>

using namespace std;

int getCnt(vector<string>& proxy, vector<string>& server, int m){
    // index表示每次遍历 serve 时的起始下标
    int index = 0, count = 0;
    while(index < m){
        int maxn = 0;//代表 index 右移的最大距离
        // 遍历代理服务器
        for(string ip : proxy){
            int j = index;
            while(j < m && ip != server[j]) j ++;
            maxn = max(maxn, j - index);
        }
        if(maxn == 0) return -1;
        count ++;
        index += maxn;
    }
    return count - 1;
}

int main(){
    int n, m;
    while(cin >> n){
        vector<string> proxy(n);
        unordered_map<string, int> mp;
        for(int i = 0; i < n; i ++){
            cin >> proxy[i];
            mp[proxy[i]] = 1;
        }
        cin >> m;
        vector<string> server(m);
        for(int i = 0; i < m; i ++)
            cin >> server[i];
        cout << getCnt(proxy, server, m);
    }
}

区间贪心🧡
每次选择结束时间最早的,让后面空余时间最多

#include<iostream>
#include<algorithm>
using namespace std;
struct node{
	int l,r;
}a[105]; 
bool camp(node a, node b){
	return a.r<b.r;
}
int n;
int ans=1;//注意题意 
int main(){
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i].l>>a[i].r;
	}
	sort(a,a+n,camp);
	int temp = a[0].r;//最早结束时间
	for(int i=1;i<n;i++){
		if(a[i].l>=temp){//开始时间>=结束时间 
			ans++;
			temp=a[i].r;
		} 
	}
	cout<<ans<<endl;
}
/*
12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
0
*/

KY155 To Fill or Not to Fill(代码量较多学思想)
贪心,每次选油价最低的,然后对路程进行覆盖
注意细节!

if(fill == 1)
if(fill = 1 )
#include<iostream>
#include<algorithm>
/*
测试用例 
50 1300 12 8
6.00 1250
7.00 600
7.00 150
7.10 0
7.20 200
7.50 400
7.30 1000
6.85 300
50 1300 12 2
7.10 0
7.00 600

输出结果 
749.17
The maximum travel distance = 1200.00
*/
using namespace std;
struct Station{
	double price;
	int distance;
}; 
bool camp(Station a, Station b){
	return a.price<b.price;
}

int main(){
	int cmax,d,davg,n; //最大容量,行驶距离, 每单位油可行驶距离,站数量 
	while(cin>>cmax>>d>>davg>>n){
		Station station[n];
		bool flag[d+1];//标记是否走过
		for(int i=1;i<=d;i++)flag[i]=0; 
		for(int i=0;i<n;i++){
			cin>>station[i].price>>station[i].distance; 
		} 
		sort(station,station+n,camp);
		double currentprice = 0;
		for(int i=0;i<n;i++){
			int currentdistance=0;//此站台加油后行驶的距离 
			for(int j=station[i].distance+1;j<=cmax*davg+station[i].distance;j++){
				if(flag[j]==false){
					flag[j]=true;
					currentdistance++;
				}
				//行驶完成或油用完
				if(j==d||j==station[i].distance+cmax * davg){
					currentprice += station[i].price*currentdistance/(davg*1.0); 
					break;
				} 
			}
		}
		int fill = 1;//是否走完 
		double journey=0;
		for(int i=1;i<=d;i++){
			if(flag[i]==true)journey++; 
			else {
				fill  = 0;
				break;
			}
		}
		if(fill==1){
			printf("%.2f-完成\n",currentprice);
		}else{
			printf("%.2f-未完成\n",journey);
		}
	}	
}

5递归与分治

汉诺塔3
假设从一个状态到另一个状态要f(n),总结出f(n)和f(n-1)表达式,同时有最终结果值

#include<iostream>
using namespace std;
/*
1
3
12
*/
long long f(int x){
	if(x==1){
		return 2;
	}else {
		return 3*f(x-1)+2;
	}
}
int main(){
	int n;
	while(~scanf("%d",&n) ){
		cout<<f(n)<<endl;
	}
	return 0;
} 

树节点分治

#include<iostream>
using namespace std;
/*
3 12
0 0

4
*/
int  f(int m,int n){
	if(m>n){
		return 0;
	}else{
		return 1+f(m*2,n)+f(m*2+1,n);
	}
}
int main(){
	int m,n;//根  节点 
	while(scanf("%d %d",&m,&n) !=EOF){
		cout<<f(m,n)<<endl;
	}
	return 0;
} 

6动态规划

最大子列和

dp[i]=max(dp[i-1]+a[i],a[i]);
//dp含义:以a[i]结尾的最大子列和

最长递减子序列
并不是连续的

	for(int i=0;i<n;i++){
		dp[i] = 1;//初始化为1 
		for(int j=0;j<i;j++){
			if(a[j]>=a[i]){
				dp[i] = max(dp[j]+1,dp[i]);
			}
		}
		ans = max(dp[i],ans);
	}

最长公共子序列

状态转移方程为:

当s1[i] = s2[j]时: dp[i][j] = dp[i-1][j-1]+1;
当s1[i] != s2[j]时: dp[i][j] = max(dp[i-1][j],dp[i][j-1]); 
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
/*
abcd
cxbydz
2
*/
const int maxn = 1001;
string s1;
string s2;

int main(){
	while(cin>>s1>>s2){
		int n = s1.length();
		int m = s2.length();
		int dp[n+1][m+1];
		memset(dp,0,sizeof(dp));
		//dp[i+1][j+1]  
		//以s1[i]为结尾 和以s2[j]为结尾村存在的最长公共子序列 
		int ans =0;
		for(int i=1;i<n+1;i++){
			for(int j=1;j<m+1;j++){
				if(s1[i-1] == s2[j-1]){
					//dp向后移动一个位置防止i-1越界 
					dp[i][j] = dp[i-1][j-1]+1;
				}else{
					dp[i][j] = max(dp[i-1][j],dp[i][j-1]); 
				} 
			}
		}
		cout<<dp[n][m]<<endl;
	}
	
} 

背包问题
01背包模板

#include<iostream>
#include<cstring>
using namespace std;
int c,n;
int ans = 0; 
int main(){
	while(cin>>c>>n){
		int p;//价格 
		int v;//价值 
		int dp[c+1];	
		memset(dp,0,sizeof(dp)); 
		for(int i=0;i<n;i++){
			cin>>p>>v;//价格 价值 
			for(int j=c;j>=p;j--){ 
				dp[j] = max(dp[j-p]+v,dp[j]);
			}
		}
		cout<<dp[c];
	} 
 
}

KY14 最小邮票数
求最小,初始值为最大

if(j==v)dp[j]=1;//初值 
else dp[j] = min(dp[j-v]+1,dp[j]);
#include<iostream>
#include<cstring>
/*
10
5
1 3 3 3 4

3
*/
using namespace std;
const int INF = 0x3ffffff;
int c,n;
int main(){
	int v;//价值 
	cin>>c>>n;	
	int dp[c+1];
	for(int i=0;i<=c+1;i++){
		dp[i]=INF;
	} 
	for(int i=0;i<n;i++){
		cin>>v;//价值 
		for(int j=c;j>=v;j--){
			if(j==v){
				dp[j]=1;//初值 
			}
			else dp[j] = min(dp[j-v]+1,dp[j]);
		}
	}

	if(dp[c]!=INF){
		cout<<dp[c];
	}else	cout<<0;	
}

完全背包
和01相同,不过顺序计算

for(int j=p;j<=p;j++)dp[j] = min(dp[j-p]+v,dp[j]);

多重背包
多一层循环
优化 …2^c

#include<iostream>
#include<cstring>
using namespace std;
int v[510],w[510],s[510],dp[6100];
int main(){
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>v[i]>>w[i]>>s[i];
	for(int i=1;i<=n;i++){
		for(int j=m;j>=1;--j){
			for(int k=0;k<=s[i]&&j>=k*v[i];k++){
				//第j个物品 拿k个 
				dp[j] = max(dp[j],dp[j-k*v[i]]+k*w[i]);
			}
		}
	} 
	cout<<dp[m]; 
 
}

复试

nbuoj+洛谷基础算法题

1224 哥德巴赫猜想(2)

题目描述
所谓哥德巴赫猜想,就是指任何一个大于2的偶数,都可以写成两个素数的和。现在输入一个偶数,要求寻找两个素数,使其和等于该偶数。由于可能有多组素数对满足条件,所以本题要求输出两数差最小的那两个素数。
注意 / 和% 的区别
以及函数调用求素数

#include<iostream>
using namespace std;
int issu(int a){
	int res=1;
	for(int i=2;i<a-1;i++){
		if(a%i==0){
			res=0;
			break;
		}
	}
	return res;
}
int main(){
	int n;
	cin>>n;
	int h=n/2;
	for(int i=h;i>1;i--){
		if(issu(i)&&issu(n-i)){
			cout<<i<<" "<<n-i<<endl;
			return 0;
		}
	}
}

1171 多个数的最小公倍数

题目描述
也许你已经会了求2个数字最小公倍数的方法,但是如果求多个数字的最小公倍数,你又能找到办法吗?
使用set标记break节省时间

#include<iostream>
using namespace std;
int main(){
	int n;
	int a[101];
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	for(int i=1;;i++){
		int set=1;//是 
		for(int j=0;j<n;j++){
			if(i%a[j]!=0){
				set=0;//不是 
				break;
			}
		}
		if(set==1){
			cout<<i<<endl;
			break;
		}
	}
}

1188 数字移位

题目描述
有n个整数,要求将前面各数字顺序向后移动m个位置,并将最后面的m个数变成最前面m个数。

#include<bits/stdc++.h>
using namespace std;
void reverse(int a[],int l,int r){
	int temp=0;
	int mid=(r-l+1)/2; //中间位置 
	for(int i=0;i<mid;i++){
		temp=a[i+l];
		a[i+l]=a[r-i];
		a[r-i]=temp;
	}
}
int main(){
	int n=0,m=0;
	int a[101];
	cin>>n>>m;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	reverse(a,0,n-1);
	reverse(a,0,m-1);
	reverse(a,m,n-1);
	for(int i=0;i<n-1;i++){
		cout<<a[i]<<" ";
	}
	cout<<a[n-1]<<endl;
}

1195 巧妙推算走楼梯

题目描述
有一楼梯共M级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第M级,共有多少种走法?
后面数据以前面为基础进行、使用相同算法

#include<iostream>
using namespace std;
int a[45]={0};

int main(){
	int n;
	int m;
	cin>>n;
	a[0]=0;
	a[1]=1;
	a[2]=1;
	a[3]=2;
	for(int i=4;i<42;i++){
		a[i]=a[i-1]+a[i-2];
	}
	for(int i=0;i<n;i++){
		cin>>m;
		cout<<a[m]<<endl;
	}
} 

P1115 最大子段和(动态规划)

给出一个长度为 n 的序列 a,选出其中连续且非空的一段使得这段和最大。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n[200001],p,ans[200001]={0};
    int sum=-9999999;//|x|<=10000   QWQ
    cin>>p;
    for(int i=1;i<=p;i++)
    {
        cin>>n[i];//输入
        ans[i]=max(ans[i-1]+n[i],n[i]);//DP
        sum=max(sum,ans[i]);//取最大值也同时进行,节约时间
    }
    cout<<sum;//直接输出
    return 0;
}

P1873 砍树(二分查找)未完成

P1223 排队接水(贪心最简单)

在这里插入图片描述
输出序号可以用结构体方式

那么针对这两个元素:就有两种排列情况:

1.ai排在bi前面那么有总时间:t1=ai+ai+bi.

2.bi排在ai前面那么有总时间:t2=bi+bi+ai.

##于是由ai<bi得出 t1<t2—》变一下式子—》ai+ai+bi<bi+bi+ai;

再化简不等式得出ai<bi

于是得出结论:当ai在bi前面时,时间为最小值。

于是反推回总体,两两相较,那么越小的应该越排在前面,以至于总时间越小

P1090 合并果子(贪心)(STL)

在这里插入图片描述
STL优先队列

#include<iostream>
#include<queue>
using namespace std;
priority_queue< int,vector<int>,greater<int> >q;
//注意格式 !空格 pop出最小的那个
int main(){
	int n;
	int a;
	int sum=0;
	cin>>n;
	while(n--){
		cin>>a;
		q.push(a);
	}
	while(q.size()>=2){
		int a=q.top();
		q.pop();
		int b=q.top();
		q.pop();
		q.push(a+b);
		sum+=a+b;
	}
	cout<<sum;
}

自定义

#include<queue>
struct Node{
    int x,y;
    Node(int a=0, int b=0):
        x(a), y(b) {}
};
 
struct cmp{
    bool operator()(Node a, Node b){
        if(a.x == b.x)    return a.y>b.y;
        return a.x>b.x;
    }
};
    priority_queue<Node, vector<Node>, cmp>p;

P1219 八皇后(搜索深搜+回溯)

在这里插入图片描述
注意for循环从1开始

#include<iostream>
using namespace std;
int ans[14];//结果 
int check[3][28]={0};//列,左右斜线
int sum=0;
int n;
void eq(int line){
	if(line>n){
		sum++; 
		if(sum>3)return;
		else
		{
			for(int i=1;i<=n;i++)
				cout<<ans[i]<<" ";
			cout<<endl;
			return;
		} 	
	}
	for(int i=1;i<=n;i++){//列遍历 有无  两斜线有无 
		if((!check[0][i])&&(!check[1][i+line])&&(!check[2][line-i+n])){
		//规律
			ans[line]=i;
			check[0][i]=1;check[1][i+line]=1;check[2][line-i+n]=1;
			eq(line+1);//回溯搜索下一行 
			check[0][i]=0;check[1][i+line]=0;check[2][line-i+n]=0;
			//复原 
		}
	}
} 
int main(){
	cin>>n;
	eq(1);//行 
	cout<<sum;
	return 0;
}

P1443 马的遍历(搜索广度优先队列)

#include<bits/stdc++.h>
#define re(i,a,b) for(int i=(a);i<=(b);i++) 
using namespace std;
struct A{
	int x,y,cnt;
};
int mp[401][401];
bool vis[401][401];
//int xx[]={1,1,-1,-1,2,2,-2,-2};
//int yy[]={2,-2,2,-2,1,-1,-1,1};
int xx[]={1,2,-1,-2,1,2,-1,-2};
int yy[]={2,1,2,1,-2,-1,-2,-1};
int main(){
	re(i,1,400)
	re(j,1,400)
	mp[i][j]=-1;
	int x1,y1,m,n;
	cin>>m>>n>>x1>>y1;
	queue<A>q;
	q.push(A{x1,y1,0});
	vis[x1][y1]=1;//存入即遍历到 
	mp[x1][y1]=0;
	while(!q.empty()){
		for(int i=0;i<8;i++){
			int dx=xx[i]+q.front().x;
			int dy=yy[i]+q.front().y;
			if(dx>=1&&dx<=m&&dy>=1&&dy<=n&&vis[dx][dy]==0){
				q.push(A{dx,dy,q.front().cnt+1});
				vis[dx][dy]=1;
				mp[dx][dy]=q.front().cnt+1;
			}
		}
		q.pop();//用完后出队列 
	}
	re(i,1,m){
		re(j,1,n){
			//cout<<mp[i][j]<<" ";	
			printf("%-5d",mp[i][j]); 
		}
		cout<<endl;
	}
	return 0;
}

P1259 黑白棋子的移动(递归)

#include<iostream>
using namespace std;
int n,st,sp;
char c[101];
void print()                                  //打印
{
	int i;
	cout<<"step "<<st<<':';
	for (i=1;i<=2*n+2;i++) cout<<c[i];
	cout<<endl;
	st++;
}
void init(int n)                             //初始化
{
	int i;
	st=0;
	sp=2*n+1;
	for (i=1;i<=n;i++) c[i]='o';
	for (i=n+1;i<=2*n;i++) c[i]='*';
	c[2*n+1]='-';c[2*n+2]='-';
	print();
}
void move(int k)                            //移动一步
{
	int j;
	for (j=0;j<=1;j++) 
	{
	   c[sp+j]=c[k+j];
	   c[k+j]='-';
	}
	sp=k;//上个空位 
	print();
}
void mv(int n)                                       //主要过程
{
	int i,k;
	if (n==4)                //n等于4的情况要特殊处理
	{
		move(4); move(8); move(2); move(7); move(1);
		}
	else
	{
		move(n); move(2*n-1); mv(n-1);
	}
}
int main()
{
	cin>>n;
	init(n);
	mv(n);
}

P1969 积木大赛(实验7)

F1规律

#include <iostream>
using namespace std;
int main()
{
    int n,a,last=0,ans=0;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a;
        if(a>last)ans+=(a-last);
        cout<<ans<<" "; 
        last=a;
        cout<<last<<endl;
    }
    cout<<ans<<endl;
}

P1318 积水面积(c++?)

import java.util.Scanner;
import java.util.Stack;
class A{
    A(int h,int i){
        height =h;
        index=i;
    }
    int height;
    int index;
}
public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int n,res=0;
        Stack<A>s=new Stack<A>();
        A a= new A(0,0);
        s.push(a);
        Scanner scan=new Scanner(System.in);
        n=scan.nextInt();
        for(int i=1;i<=n;i++){
            A top=s.peek();
            a=new A(scan.nextInt(),i);
            while(s.size()>1&&top.height<a.height){//有积水
                int h=top.height;
                s.pop();
                top=s.peek();
                int w = a.index-top.index-1;
                if(a.height>top.height)h=top.height-h;
                else h=a.height-h;
                res+=w*h;
                //System.out.println(w+" "+h);

            }
            if(a.height>=top.height)s.pop();
            s.push(a);
        }
        System.out.println(res);
    }

}

P1048 采药(实验8 )🧡

01背包问题
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int m,t;
int dp[1005];
int c;//时间
int v;//价值
int main(){
	cin>>t>>m;
	for(int i=1;i<=m;i++){//物品序号 
		cin>>c>>v;//和上一个物品没有关联 
		for(int j=t;j>=c;j--){//时间 
			dp[j]=max(dp[j-c]+v,dp[j]);
			//倒退 有这个或没有
		}
	}
	cout<<dp[t];
	return 0;
} 

P1095 守望者的逃离(未完成)

现在已知守望者的魔法初值M,他所在的初始位置与岛的出口之间的距离S,岛沉没的时间T。你的
任务是写一一个程序帮助守望者计算如何在最短的时间内逃离荒岛,若不能逃出,则输出守望者在剩下的
时间内能走的最远距离。
CSDN

#include<cstdio> 
#include<cstring>
#include<iostream> 
#include<algorithm>
#include<cmath>
using namespace std;
int main()
{
    int m,s,t,now=0;
    cin>>m>>s>>t;
    int s1=0,s2=0;//存放跑步能走的距离和用闪烁能走的距离
    for(int i=1;i<=t;i++)//一个个时间去推
    {
        s1+=17;//闪现和跑步分批进行
        if(m>=10) {s2+=60;m-=10;}//能够闪现这肯定要闪现的,
        else m+=4;//没蓝这一回合就用来回蓝
        if(s2>s1) s1=s2;//闪现的快了就把跑步的替换成闪现的
        if(s1>s){//跑出去了就输出当前时间
            cout<<"Yes"<<endl<<i<<endl;
            return 0;
        }
    }
    cout<<"No"<<endl<<s1<<endl;//时间都用完了还没跑出去,输出“No”和s1的值,(由于闪现可走距离一旦大于跑步的跑步的距离就会被替换,这时跑的距离远的一定是s1)
}

P1020 导弹拦截

P1021 邮票面值设计(参考答案)

#include<iostream>
#include<cstring>//头文件
using namespace std;
int a[17],n,k,ans[17],maxn;//a【】表示这种方法的邮票,ans【】表示如今取得的解即要输出的
int dp(int t,int mx){
    int f[50000];//f[i]为拼i所需的最少数的个数
    f[0]=0;//边界
    for(int i=1;i<=a[t]*n;i++)
      f[i]=50000;//赋初值赋一个尽可能地大就可以了
    for(int i=1;i<=t;i++)            //从第一位找到目前的位数把所有已找的邮票都枚举 
      for(int j=a[i];j<=a[t]*n;j++)   //因为不可能找到比自己小的数,所以从自己开始找 
        f[j]=min(f[j],f[j-a[i]]+1);    //比较上几次已找到的最小需要位数和即将要找的相比较,取较小值 
for(int i=1;i<=a[t]*n;i++)
      if(f[i]>n)//如果所需最小的个数大于n就意味着这种情况不符合,但f【i-1】是符合的不然f【i-1】就会判断所以不符合返回i-1
        return i-1;
    return a[t]*n;//如果到a【t】*n的f【i】都满足意味着能取到的最大连续数就是a【t】*n
}
void dfs(int t,int mx){              // 为什么全部找完:因为多几张邮票肯定比少几张邮票可能的情况多,所以全部找完是最好的  
    if(t==k+1){        //如果所有邮票数已经找完,那么就和 maxn比较谁更大   
        if(mx>maxn){
            maxn=mx;
            for(int i=1;i<=t-1;i++)
              ans[i]=a[i];} //保存所需要的邮票面值  
        return;
        }
    for(int i=a[t-1]+1;i<=mx+1;i++){  //继续找:为了避免重复,下一张邮票要比上一张邮票大,所以上边界是a[t-1]+1,同时它不能比最大连续值+1还大,不然最大连续值的下一个数就永远连不起来了 
      a[t]=i;
      int x=dp(t,mx);   //动归寻找此时的最大连续数 
      dfs(t+1,x);
    }
}
int main(){
    cin>>n>>k;
    dfs(1,0);  //先从第一张开始找,第一张前面没有数,所以所连续的最大数为 0 
    for(int i=1;i<=k;i++)//输出 注意打空格以及大写换行即可
      cout<<ans[i]<<" ";
    cout<<endl;
    cout<<"MAX="<<maxn<<endl;
    return 0;
}

抓码每日一题(字符串)

链接

部分A+B

正整数A的“DA(为1位整数)部分”定义为由A中所有DA组成的新整数PA。例如:给定A = 3862767,DA= 6,则A的“6部分”PA是66,因为A中有2个6。
现给定A、DA、B、DB,请编写程序计算PA + PB。
字符串和数字转化注意 - ‘0’

//输出样例1:
//3862767 6 13530293 3
//输出样例2:
//399
#include<iostream>
using namespace std;
string a,b;
int da,db;
int main(){
	int cnta = 0;
	int cntb = 0;
	int pa = 0;
	int pb = 0;
	cin>>a>>da>>b>>db;
	for(int i=0;i<a.length();i++){ 
		if(da==a[i]-'0'){//
			cnta++;
		}
	}
	for(int i=0;i<b.length();i++){
		if(db==b[i]-'0'){
			cntb++;
		}
	}
	while(cnta--){
		pa=pa*10+da;
	}
	while(cntb--){
		pb=pb*10+db;
	}
	cout<<pa+pb;
} 

组个最⼩数

注意思想输出最小的数

//输出样例:
//2 2 0 0 0 3 0 0 1 0
//输出样例:
//10015558
//最小数 
#include<iostream>
using namespace std;
int a[10]={0};
int main(){
	for(int i=0;i<10;i++){
		cin>>a[i];
	}
	//首先输出第一个不为0
	for(int i=1;i<10;i++){
		if(a[i]!=0){
			cout<<i;
			a[i]--;
			break;
		}
	}
	for(int i=0;i<a[0];i++){
		cout<<0;
	} 
	for(int i=1;i<10;i++){
		while(a[i]--){
			cout<<i;
		}
	}
	return 0;
}

4翻转链表

#include<iostream>
#include<algorithm>
/*
测试用例 
00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

输出结果 
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1
*/
using namespace std;
int first, k, n, temp; 
int data[100005], next[100005], list[100005];
//数值列表  下一节点列表   顺序列表 
int main(){
	cin>>first>>k>>n;
	for(int i=1;i<n;i++){
		cin>>temp;
		cin>>data[temp]>>next[temp];
	}
	int sum = 0;
	while(first!=-1){
		list[sum++] = first;//list 0 = 地址 
		first = next[first];//下一地址 
	}
	
	for(int i=0;i<(sum -= sum%k);i+=k)
		reverse(list + i,list+i+k);
	for(int i=0;i<sum-1;i++){
		printf("%05d %d %05d\n",list[i],data[list[i]],list[i+1]);
	}
	printf("%05d %d -1\n",list[sum-1],data[list[sum-1]]);
}

5打印沙漏(找规律a)

*****
 ***
 *
***
*****

假设扩展的层数为 i,则扩展出去的上边需要的所有符号个数为3 + 5 + 7 + …+ (2i+1) = (3 + 2i + 1) * i / 2 = i * (i + 2),扩展出去的下边与上边同样多所以乘以2,加上最重要那⼀⾏1个符号,所以 总共需要2 * i * (i + 2) + 1个符号,所以i从0到N,找满⾜(2 * i * (i + 2) + 1)> N的最小的 i。

6旧的键盘

toupper
string::npos

int main(){
	string s1,s2;
	cin>>s1>>s2;
	string ans="";
	for(int i=0;i<s1.length();i++){
		if(s2.find(s1[i]) == string::npos &&ans.find(toupper(s1[i])) == string::npos){
			ans+=toupper(s1[i]);
		} 
	}
	cout<<ans;
}
t = N / 2 + N % 2,表示偶数等于除以2,
奇数要除以2加1的意思,这样才能满⾜四舍五⼊。

11有几个PAT

注意思想,每次遇到A统计一次。

要想知道构成多少个PAT,那么遍历字符串后对于每⼀A,
它前⾯的P的个数和它后⾯的T的个数的乘积就是能构成的PAT的个数。
然后把对于每⼀个A的结果相加即可。
只需要先遍历字符串数⼀数有多少个T,然后每遇到⼀个T,countt–;
每遇到⼀个P,countp++;然后⼀遇到字⺟A就countt * countp。
#include <iostream>
#include <vector>
using namespace std;
int main() {
	string s;
	cin>>s;
	int len = s.length();
	int ans = 0,coutp=0,coutt=0	;
	for(int i=0;i<len;i++){
		if(s[i]=='T'){
			coutt++;
		}
	}//先统计T个数 
	for(int i=0;i<len;i++){
		if(s[i]=='T')coutt--;
		if(s[i]=='P')coutp++;
		if(s[i]=='A')ans= (ans+(coutp*coutt)%10000000007)%10000000007;
	}
	cout<<ans;
    return 0; 
}

29数字加密

本题要求实现⼀种数字加密⽅法。⾸先固定⼀个加密⽤正整数A,对任⼀正整数B,将其每1位数字与A的对应位置上的数字进⾏以下运算:对奇数位,对应位的数字相加后对13取余——
这⾥⽤J代表10、Q代表11、K代表12;

输⼊样例:
1234567 368782971
输出样例:
3695Q8118

字符串逆置加减处理

#include<iostream>
#include<algorithm>
using namespace std;
int main(){
	string a,b,c;
	cin >> a >> b;
	int lena = a.length(),lenb = b.length();
	reverse(a.begin(),a.end());//逆置后 
	reverse(b.begin(),b.end());
	if(lena > lenb){//补0 
		b.append(lena - lenb ,'0');
	}
 	if(lenb > lena){
		a.append(lenb - lena ,'0');
	}
	char str[14] = {"0123456789JQK"};
	//数组! 
	for(int i=0;i<a.length();i++){
		if(i%2==0){//奇数 
			c+=str[(a[i]- '0' + b[i] - '0')%13];
		}else{
			int temp = b[i]-a[i];
			if(temp<0){
				temp = temp+10;	
			}
			c += str[temp];
		}
	} 
	cout<<c.length();
	for(int i= c.length()-1;i>=0;i--){
		cout<<c[i];1234567 368782971	
	}
	return 0;
}

王道上机书

1暴力

枚举
反序数+注意初试化

#include<iostream>
using namespace std;
int rev(int x){
	int re=0;//注意初始化为0!!! 
	while(x!=0){
		re*=10;
		re += x%10;
		x/=10;
	}
	return re;
}

int main(){
	for(int i =1000;i<=9999;i++){
		if(i*9 == rev(i)){
			cout<<i<<endl;
		}
	}
}

模拟
画图:模拟数组
寻找规律啊
题目:Hello World for U#

n2随长度增加呈现出一个有规律的数列,3个一组
从最短长度5开始,n2为:3,4,3,4,5,4,5,6,5,6,7,6,7,8,7,8,9,8,9,10......
int suren2(int len){//计算n2
    if(len%3==0||len%3==2) return len/3+2;
    else return len/3+1;
}

日期问题

#include<iostream>
using namespace std;
//日期问题 
int year,month,day;
int ans=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}
};
bool isLeapyear(int year){//4 并且 100  或400 
	return (year%4==0&&year%100==0)||(year%400==0);
} 
int main(){
	while(scanf("%d%d%d",&year,&month,&day) != EOF){
	//循环输入!!!
		for(int i=1;i<month;i++){
			ans+=daytab[isLeapyear(year)][i]; 
		}
			ans+=day;
			cout<<ans;
	}
}

其它模拟
区间除树问题:最后可以不用遍历,当为1变false,数量–;
手机键盘:注意建立模拟记录数组,keytable【】

输入
scanf
%c 读入一个字符
%d 读入十进制整数
%s 读入一个字符串,遇空格、制表符或换行符结束。
输出
yyyy-mm-dd形式可能有0格式凑0
printf("%04d-%02d-%02d\n",year,month,day);

2二分查找

KY199 查找

#include<iostream>
#include<algorithm>
using namespace std;
int n, m;
const int MAXN = 1000;
int a[MAXN];
bool BinarySearch(int target, int n) {
    int l = 0;
    int r = n;
    while (l <= r) {
        int middle = (l + r) / 2;
        if (a[middle] < target) {
            l =  middle + 1;
        } else if (a[middle] > target) {
            r = middle - 1;
        } else {
            return true;
        }
    }
    return false;
}
int main() {
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    sort(a, a + n);
    cin >> m; //查找个数
    for (int i = 0; i < m; i++) {
        int t;
        cin >> t;
        if (BinarySearch(t, n)) {
            cout << "YES" << endl;
        } else cout << "NO" << endl;
    }
    return 0;
}
/*
4
9 8 17 6
*/

3字符串相关知识

s.find()//返回查找位置
if(t.find("ewq")==string::npos){
		cout<<"nofind";//未查找到为string::nops
}
	
cout<<t.substr(1,3);//截取字符串(开始,个数)

string str;
getline(cin,str);
cout<<str;//getline可以不考虑空格

//'a''z'相差25
cout<<'A'-'a'; //-32

str[i] = (str[i]-'A'-5+26)%26+'A';
//加减循环算法,+26%26可以抵消不用分情况

KY127 统计字符(字符存储)

#include <iostream>
#include <algorithm>
using namespace std;
string str1,str2;
int number[128];
int main()
{
	while(getline(cin,str1)){
		if(str1=="#"){
			break;
		}
		getline(cin,str2);
		for(int i=0;i<128;i++)number[i]=0;//注意清0 
		for(int i=0;i<str2.length();i++){
				number[str2[i]]++;			
		}
		for(int i=0;i<str1.length();i++){
			cout<<str1[i]<<" "<<number[str1[i]]<<endl;
		}
	}
}
/*
I
THIS IS A TEST
i ng
this is a long test string
#

I 2
i 3
  5
n 2
g 2

*/ 

延迟的回文数
字符串相加算法,高精度

#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
/*
97152

97152 + 25179 = 122331
122331 + 133221 = 255552
255552 is a palindromic number.
*/
string rev(string t){//翻转 
	reverse(t.begin(),t.end());
	return t;
}
//高精度
string add(string s1,string s2){
	string s = s1;
	int carry=0;
	for(int i = s1.length()-1; i>=0; i--){
		s[i] = (s1[i]-'0' + s2[i] - '0' + carry) % 10 + '0';
		carry = (s1[i]-'0' +  s2[i]-'0' + carry)/10;
	} 
	
	if(carry > 0 )s = "1"+s ;//向前进位 
	return s; 
}

int main(){
	string t;
	cin>>t;
	int cnt=10;
	
	if(t == rev(t)){
		cout<<"yes";
		cout<<t;
	}
	
	while(cnt--){
		
		string temp = t;
		if(rev(t)==temp){//成功 
			cout<<t<<"yes"<<endl;//输出 
			return 0;
		}
		
		cout<<t<<"+"<<rev(t)<<endl;
		t = add(temp,rev(t)); 
		//超过10次 
	}
	cout<<"Not found in 10 iterations"<<endl;
} 

23复试:互评成绩计算

#include <iostream>
#include <algorithm>
using namespace std;
/*
互评成绩计算
 
*/
int main(){
	int n,m;
	cin>>n>>m;
	for(int i= 0;i<n;i++){
		int cnt = -2;
		int g1=0,g2=0,temp,maxn = -1,minn = m+1;
		cin>>g1;
		for(int i=1;i<n;i++){
			cin>>temp;
			if(temp>=0&&temp<=m){
				if(temp > maxn) maxn = temp;
				if(temp < minn) minn = temp;
				cnt++;//计合规分数 
				g2+=temp;//分组加分 
			}
		}
	 	cout << int((((g2-maxn-minn)* 1.0 / cnt) + g1) / 2 + 0.5) << endl;
	 //舍四进五 + 0.5int() 
	} 
}

字符串KMP(待完成)

4贪心

例题🧡
01背包
部分包
购买贺年卡.
硬币问题
删数问题
拦截导弹问题添加链接描述
排队接水
均分纸牌

senior‘s gun

	for(int i=0;i<n;i++){
		if((i>=m)&&gun[i]>=monstor[i]){
			//还有怪物射杀并且可以杀死怪物 
			break; 
		}
		ans+=(gun[i]-monstor[i]);
	}

KY4 代理服务器(未完成)
其实就是想要尽可能使用和要访问服务器没有交集的代理服务器。
如果要访问的服务器中没有和代理服务器 IP 相同的,返回 0
如果有相同的,那么每个代理服务器都在某一个位置相同,比如例子中的分别在 1、4、2 处相同,那么贪心策略取最远相同的,然后对剩下的再次进行判断即可。
因为服务器 IP 没有说明是否不重复,所以一个代理服务器 IP 可能在多个位置与要访问的服务器 IP 相同,所以取最远的位置其实是第一次相同时的最远位置。然后更新遍历 sever 的起始地址,直到遍历完全。

#include<iostream>
#include<vector>

using namespace std;

int getCnt(vector<string>& proxy, vector<string>& server, int m){
    // index表示每次遍历 serve 时的起始下标
    int index = 0, count = 0;
    while(index < m){
        int maxn = 0;//代表 index 右移的最大距离
        // 遍历代理服务器
        for(string ip : proxy){
            int j = index;
            while(j < m && ip != server[j]) j ++;
            maxn = max(maxn, j - index);
        }
        if(maxn == 0) return -1;
        count ++;
        index += maxn;
    }
    return count - 1;
}

int main(){
    int n, m;
    while(cin >> n){
        vector<string> proxy(n);
        unordered_map<string, int> mp;
        for(int i = 0; i < n; i ++){
            cin >> proxy[i];
            mp[proxy[i]] = 1;
        }
        cin >> m;
        vector<string> server(m);
        for(int i = 0; i < m; i ++)
            cin >> server[i];
        cout << getCnt(proxy, server, m);
    }
}

区间贪心🧡
每次选择结束时间最早的,让后面空余时间最多

#include<iostream>
#include<algorithm>
using namespace std;
struct node{
	int l,r;
}a[105]; 
bool camp(node a, node b){
	return a.r<b.r;
}
int n;
int ans=1;//注意题意 
int main(){
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i].l>>a[i].r;
	}
	sort(a,a+n,camp);
	int temp = a[0].r;//最早结束时间
	for(int i=1;i<n;i++){
		if(a[i].l>=temp){//开始时间>=结束时间 
			ans++;
			temp=a[i].r;
		} 
	}
	cout<<ans<<endl;
}
/*
12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
0
*/

KY155 To Fill or Not to Fill(代码量较多学思想)
贪心,每次选油价最低的,然后对路程进行覆盖
注意细节!

if(fill == 1)
if(fill = 1 )
#include<iostream>
#include<algorithm>
/*
测试用例 
50 1300 12 8
6.00 1250
7.00 600
7.00 150
7.10 0
7.20 200
7.50 400
7.30 1000
6.85 300
50 1300 12 2
7.10 0
7.00 600

输出结果 
749.17
The maximum travel distance = 1200.00
*/
using namespace std;
struct Station{
	double price;
	int distance;
}; 
bool camp(Station a, Station b){
	return a.price<b.price;
}

int main(){
	int cmax,d,davg,n; //最大容量,行驶距离, 每单位油可行驶距离,站数量 
	while(cin>>cmax>>d>>davg>>n){
		Station station[n];
		bool flag[d+1];//标记是否走过
		for(int i=1;i<=d;i++)flag[i]=0; 
		for(int i=0;i<n;i++){
			cin>>station[i].price>>station[i].distance; 
		} 
		sort(station,station+n,camp);
		double currentprice = 0;
		for(int i=0;i<n;i++){
			int currentdistance=0;//此站台加油后行驶的距离 
			for(int j=station[i].distance+1;j<=cmax*davg+station[i].distance;j++){
				if(flag[j]==false){
					flag[j]=true;
					currentdistance++;
				}
				//行驶完成或油用完
				if(j==d||j==station[i].distance+cmax * davg){
					currentprice += station[i].price*currentdistance/(davg*1.0); 
					break;
				} 
			}
		}
		int fill = 1;//是否走完 
		double journey=0;
		for(int i=1;i<=d;i++){
			if(flag[i]==true)journey++; 
			else {
				fill  = 0;
				break;
			}
		}
		if(fill==1){
			printf("%.2f-完成\n",currentprice);
		}else{
			printf("%.2f-未完成\n",journey);
		}
	}	
}

5递归与分治

汉诺塔3
假设从一个状态到另一个状态要f(n),总结出f(n)和f(n-1)表达式,同时有最终结果值

#include<iostream>
using namespace std;
/*
1
3
12
*/
long long f(int x){
	if(x==1){
		return 2;
	}else {
		return 3*f(x-1)+2;
	}
}
int main(){
	int n;
	while(~scanf("%d",&n) ){
		cout<<f(n)<<endl;
	}
	return 0;
} 

树节点分治

#include<iostream>
using namespace std;
/*
3 12
0 0

4
*/
int  f(int m,int n){
	if(m>n){
		return 0;
	}else{
		return 1+f(m*2,n)+f(m*2+1,n);
	}
}
int main(){
	int m,n;//根  节点 
	while(scanf("%d %d",&m,&n) !=EOF){
		cout<<f(m,n)<<endl;
	}
	return 0;
} 

6动态规划

最大子列和

dp[i]=max(dp[i-1]+a[i],a[i]);
//dp含义:以a[i]结尾的最大子列和

最长递减子序列
并不是连续的

	for(int i=0;i<n;i++){
		dp[i] = 1;//初始化为1 
		for(int j=0;j<i;j++){
			if(a[j]>=a[i]){
				dp[i] = max(dp[j]+1,dp[i]);
			}
		}
		ans = max(dp[i],ans);
	}

最长公共子序列

状态转移方程为:

当s1[i] = s2[j]时: dp[i][j] = dp[i-1][j-1]+1;
当s1[i] != s2[j]时: dp[i][j] = max(dp[i-1][j],dp[i][j-1]); 
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
/*
abcd
cxbydz
2
*/
const int maxn = 1001;
string s1;
string s2;

int main(){
	while(cin>>s1>>s2){
		int n = s1.length();
		int m = s2.length();
		int dp[n+1][m+1];
		memset(dp,0,sizeof(dp));
		//dp[i+1][j+1]  
		//以s1[i]为结尾 和以s2[j]为结尾村存在的最长公共子序列 
		int ans =0;
		for(int i=1;i<n+1;i++){
			for(int j=1;j<m+1;j++){
				if(s1[i-1] == s2[j-1]){
					//dp向后移动一个位置防止i-1越界 
					dp[i][j] = dp[i-1][j-1]+1;
				}else{
					dp[i][j] = max(dp[i-1][j],dp[i][j-1]); 
				} 
			}
		}
		cout<<dp[n][m]<<endl;
	}
	
} 

背包问题
01背包模板

#include<iostream>
#include<cstring>
using namespace std;
int c,n;
int ans = 0; 
int main(){
	while(cin>>c>>n){
		int p;//价格 
		int v;//价值 
		int dp[c+1];	
		memset(dp,0,sizeof(dp)); 
		for(int i=0;i<n;i++){
			cin>>p>>v;//价格 价值 
			for(int j=c;j>=p;j--){ 
				dp[j] = max(dp[j-p]+v,dp[j]);
			}
		}
		cout<<dp[c];
	} 
 
}

KY14 最小邮票数
求最小,初始值为最大

if(j==v)dp[j]=1;//初值 
else dp[j] = min(dp[j-v]+1,dp[j]);
#include<iostream>
#include<cstring>
/*
10
5
1 3 3 3 4

3
*/
using namespace std;
const int INF = 0x3ffffff;
int c,n;
int main(){
	int v;//价值 
	cin>>c>>n;	
	int dp[c+1];
	for(int i=0;i<=c+1;i++){
		dp[i]=INF;
	} 
	for(int i=0;i<n;i++){
		cin>>v;//价值 
		for(int j=c;j>=v;j--){
			if(j==v){
				dp[j]=1;//初值 
			}
			else dp[j] = min(dp[j-v]+1,dp[j]);
		}
	}

	if(dp[c]!=INF){
		cout<<dp[c];
	}else	cout<<0;	
}

完全背包
和01相同,不过顺序计算

for(int j=p;j<=p;j++)dp[j] = min(dp[j-p]+v,dp[j]);

多重背包
多一层循环
优化 …2^c

#include<iostream>
#include<cstring>
using namespace std;
int v[510],w[510],s[510],dp[6100];
int main(){
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>v[i]>>w[i]>>s[i];
	for(int i=1;i<=n;i++){
		for(int j=m;j>=1;--j){
			for(int k=0;k<=s[i]&&j>=k*v[i];k++){
				//第j个物品 拿k个 
				dp[j] = max(dp[j],dp[j-k*v[i]]+k*w[i]);
			}
		}
	} 
	cout<<dp[m]; 
 
}

7.1数组栈队列

在这里插入图片描述

#include<iostream>
#include<queue>
using namespace std;
/*
8 3 4
1 2 3 4 5 6 7 8
*/
int n,p,m;//小孩  开始 间隔
queue<int>a;
int main()
{
	cin>>n>>p>>m;
	for(int i=1;i<=n;i++){
	 	a.push(i);
	}
	for(int i=1;i<p;i++){
		a.push(a.front());
		a.pop();
	}
	int num = n;
	int i=0;
	while(num){
		int cnt = m-1;
		while(cnt--){
			a.push(a.front());
			a.pop();
		}
		//出队
		cout<<a.front();
		a.pop();
		num--;
	}
}

在这里插入图片描述

//第一个数字为所有事件
//第一个元素为1,代表进入收容所,第二个元素为动物的编号,正数代表狗,负数代表猫
//第一个元素为2,代表收养,第二个元素为0,代表所有与动物的先后,第二个数字为1,代表收养狗,若为-1
//代表是收养猫 。 不合法的直接忽略 , 输出动物的的编号 , 以空格间隔;
#include<cstdio>
#include<queue>
using namespace std;
struct Animals{
    int num;//编号
    int seq;//序号
};
int main(){
    int seq = 0;
    int n;//问题的规模
    scanf("%d",&n);
    queue<Animals> dogQue;
    queue<Animals> catQue;
    for(int i = 0 ; i < n ; ++ i ){
        int x , y;
        scanf("%d%d",&x,&y);
        if(1 == x){//动物进入收容所
 
            if( y > 0){
                Animals dog;
                dog.num = y;
                dog.seq = seq ;
                ++seq;
                dogQue.push(dog);
            }
            else{
                Animals cat;
                cat.num = y;
                cat.seq = seq ;
                ++seq;
                catQue.push(cat);
 
            }
        }
        else{//动物出收容所
            if( 0 == y ){//所有动物先后
                if(catQue.empty() && dogQue.empty()){//猫狗都空 忽略
                    continue;
                }
                else if (catQue.empty() && !dogQue.empty()
                || !dogQue.empty() && !catQue.empty() && dogQue.front().seq < catQue.front().seq){
                    //所有动物先后 ,零养狗的情况 1.猫空 狗不空 2.猫狗都不空但是 狗的seq<猫的seq
                    printf("%d ",dogQue.front().num);
                    dogQue.pop();
                }
                else{
                    printf("%d ",catQue.front().num);
                    catQue.pop();
                }
            }
            else if(1 == y){//领养狗
                if(dogQue.empty()){
                    continue;
                }
                else{
                    printf("%d ",dogQue.front().num);
                    dogQue.pop();
                }
            }
            else{//领养猫
                if(catQue.empty()){
                    continue;
                }
                else{
                    printf("%d ",catQue.front().num);
                    catQue.pop();
                }
            }
        }
    }
 
}

在这里插入图片描述

#include<iostream>
#include<stack>
using namespace std;
/*
)(rttyy())sss)(
*/
//struct node{
//	int index;
//	char c;
//};
int main()
{
	stack<int>a;	
	string t;
	cin>>t;
	for(int i=0;i<t.length();i++){
		//cout<<t;
		if(t[i]>='a'&&t[i]<='z'){
			t[i]=' ';
		}
	}
	
	
	for(int i=0;i<t.length();i++){
		if(t[i]=='('){
			a.push(i);
		}
		if(t[i]==')'){

			if(a.empty()){
				t[i]='?';	
			}
			if(!a.empty()){//符合 
				t[a.top()]=' ';
				t[i]=' ';
				a.pop();
			}
			//cout<<t;
		}
	//cout<<t;
	}
	while(!a.empty()){
		t[a.top()]='$';
		a.pop();
	}
	cout<<t;
}

7.2数据结构(排序树、搜索树)

KY212 二叉树遍历
在这里插入图片描述

#include<iostream>
#include<stack>
using namespace std;
/*
)(rttyy()sss)(
*/
void treeprint(string a,string b){
	if(a.size()!=0){
		int r = b.find(a[0]);//头所在中序位置 
		treeprint(a.substr(1,r),b.substr(0,r));//左 
		treeprint(a.substr(r+1),b.substr(r+1));//右 
		cout<<a[0];
	} 
}
int main()
{	
	string a,b;
	//a 头左     右
	//b 左     头右 
	//          r 
	//输出 左右头 
	while(cin>>a>>b){
		treeprint(a,b);
	} 
	return 0;
}

先序遍历->中序遍历数组

#include<iostream>
#include<stack>
using namespace std;
/*
abc##de#g##f###
c b e g d f a 
先序遍历->中序遍历 
*/
const int N1=1e8+5;
const int N2=1e2+5;
int pos;
char tree[N1];
char str[N1];
void create(int pos){//创建树 
	char c = str[t++];
	if(c=='#'){
		return;
	}
	tree[pos]=c;//赋值	
	create(2*pos);//更换位置 
	create(2*pos+1);
}
void traverse(int root){
	if(tree[root]==0){
		return;
	} 
	traverse(2*root);
	cout<<tree[root]<<" ";
	traverse(2*root+1);
} 
int main()
{	
	while(cin>>str){
		pos=0;
		create(1);
		traverse(1);
		cout<<endl;
	}
}

KY207 二叉排序树
在这里插入图片描述

KY223 二叉搜索树

在这里插入图片描述

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值