复试
- nbuoj+洛谷基础算法题
- 1224 哥德巴赫猜想(2)
- 1171 多个数的最小公倍数
- 1188 数字移位
- 1195 巧妙推算走楼梯
- P1115 最大子段和(动态规划)
- P1873 砍树(二分查找)未完成
- P1223 排队接水(贪心最简单)
- P1090 合并果子(贪心)(STL)
- P1219 八皇后(搜索深搜+回溯)
- P1443 马的遍历(搜索广度优先队列)
- P1259 黑白棋子的移动(递归)
- [P1969 积木大赛(实验7)](https://www.luogu.com.cn/problem/P1969)
- P1318 积水面积(c++?)
- P1048 采药(实验8 )🧡
- P1095 守望者的逃离(未完成)
- P1020 导弹拦截
- P1021 邮票面值设计(参考答案)
- 抓码每日一题(字符串)
- 王道上机书
- nbuoj+洛谷基础算法题
- 1224 哥德巴赫猜想(2)
- 1171 多个数的最小公倍数
- 1188 数字移位
- 1195 巧妙推算走楼梯
- P1115 最大子段和(动态规划)
- P1873 砍树(二分查找)未完成
- P1223 排队接水(贪心最简单)
- P1090 合并果子(贪心)(STL)
- P1219 八皇后(搜索深搜+回溯)
- P1443 马的遍历(搜索广度优先队列)
- P1259 黑白棋子的移动(递归)
- [P1969 积木大赛(实验7)](https://www.luogu.com.cn/problem/P1969)
- P1318 积水面积(c++?)
- P1048 采药(实验8 )🧡
- P1095 守望者的逃离(未完成)
- P1020 导弹拦截
- P1021 邮票面值设计(参考答案)
- 抓码每日一题(字符串)
- 王道上机书
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)
#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)
- 1171 多个数的最小公倍数
- 1188 数字移位
- 1195 巧妙推算走楼梯
- P1115 最大子段和(动态规划)
- P1873 砍树(二分查找)未完成
- P1223 排队接水(贪心最简单)
- P1090 合并果子(贪心)(STL)
- P1219 八皇后(搜索深搜+回溯)
- P1443 马的遍历(搜索广度优先队列)
- P1259 黑白棋子的移动(递归)
- [P1969 积木大赛(实验7)](https://www.luogu.com.cn/problem/P1969)
- P1318 积水面积(c++?)
- P1048 采药(实验8 )🧡
- P1095 守望者的逃离(未完成)
- P1020 导弹拦截
- P1021 邮票面值设计(参考答案)
- 抓码每日一题(字符串)
- 王道上机书
- nbuoj+洛谷基础算法题
- 1224 哥德巴赫猜想(2)
- 1171 多个数的最小公倍数
- 1188 数字移位
- 1195 巧妙推算走楼梯
- P1115 最大子段和(动态规划)
- P1873 砍树(二分查找)未完成
- P1223 排队接水(贪心最简单)
- P1090 合并果子(贪心)(STL)
- P1219 八皇后(搜索深搜+回溯)
- P1443 马的遍历(搜索广度优先队列)
- P1259 黑白棋子的移动(递归)
- [P1969 积木大赛(实验7)](https://www.luogu.com.cn/problem/P1969)
- P1318 积水面积(c++?)
- P1048 采药(实验8 )🧡
- P1095 守望者的逃离(未完成)
- P1020 导弹拦截
- P1021 邮票面值设计(参考答案)
- 抓码每日一题(字符串)
- 王道上机书
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)
#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 二叉搜索树