天梯赛学习总结

本文分享了C++编程中的实用技巧,包括字符串操作、数据类型转换、算法优化等,并介绍了动态规划、排序算法及数据结构的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这次是我第一次参加比赛,也是第一次见到大佬的学习状态,果然成功的人背后的坚辛是难以预测的,我把学长讲的东西大概总结了一下,据说比赛可以带纸质的参考资料,嘿嘿嘿。

#include<iostream>

#include<cstring>
#include<string>
#include<cmath>
#include<cstdio>
#include<map>
#include<set>
#include<algorithm>
#include<iomanip>
#include<sstream>
using namespace std;
int main()
{
return 0;
}
//用到的函数
一、string 
1、erase函数删掉指定位置字符
(1)string& erase ( size_t pos = 0, size_t n = npos );
(2)iterator erase ( iterator position );
(3)iterator erase ( iterator first, iterator last );
也就是说有三种用法:
(1)erase(pos,n); 删除从pos开始的n个字符,比如erase(0,1)就是删除第一个字符
(2)erase(position);删除position处的一个字符(position是个string类型的迭代器)
(3)erase(first,last);删除从first到last之间的字符(first和last都是迭代器)


2、截取子串
 s.substr(pos, n)    截取s中从pos开始(包括0)的n个字符的子串,并返回


3、resize(int n,char c)函数
表示调整容器的大小为n,扩容后的每个元素的值为c,默认为0
resize()会改变容器的容量和当前元素个数,如果长于规定的值,则裁掉多余的部分


4、replace


(1)、replace(int i,int num,string s)从第i个位置以后的num个字符替换为s


(2)、replace(int a,int num1,string s,int b,int num2)从第a个位置以后的num1个字符替换为s中第b个位置以后的num2的字符


PS:s.replace(0,0,s1):在s之前插入s1


s = "asd";
s1 = "123";
s.replace(0,0,s1);
输出s运行:123asd
5、find
(1)、s.find(string s1);返回s1在s中第一次出现的下标位置


string s = "123456123456";
string s1 = "123";
int a = s.find(s1);
cout<<a<<endl;
运行结果:a = 0;
(2)、s.find(string s1,int num):从下标num开始查找s1返回在s中的下标位置


string s = "123456123456";
string s1 = "123";
int a = s.find(s1,5);
cout<<a<<endl;
  运行结果:a = 6;
6、char转string


char str[10];
string s(str);//或者是s = str;
7、string转char


const char *str;
string s;
str = s.c_str();


二、四舍五入


double a = 11/2.0;
int b = (int)(a+0.5);


三、控制位数


double   fixed<<setprecision(num)(#include<iomanip>)


四、输入输出


1、scanf和string:


    string a;  
    a.resize(100); //需要预先分配空间  
    scanf("%s", &a[0]);  
    puts(a.c_str());  


2、printf和string:


   string s = "中国";


   printf("%s" , s.c_str());


3、据说面对大量数据时printf、scanf能节省时间


4、常用
scanf("%d",&int);
scanf("%lf",&double);
scanf("%f",&float);
scanf("%c",&char);
scanf("%s",&char *);//不读取空格,gets(char *)读取空格


printf("%m.nf",**):输出共占m列,其中有n位小数,如数值宽度小于m左端补空格。 
printf("%-m.nf",**):输出共占n列,其中有n位小数,如数值宽度小于m右端补空格。


五、读取输入的空格
cin.get()


六、字符转换数字


‘0’ - 48 = 0;


七、大写小写字母


小写-32=大写


八、string转为int int转为string


int Si(string a)
{
stringstream s;
s.str(a);
int c;
s>>c;
return c;
}
string Is(int a)
{
stringstream s;
s<<a;
string ss = s.str();
return ss;
}


九、判断素数


bool judge(long long int num)
{
if(num==1)//注意1 的情况
return false;
long long n = sqrt(num);
for(long long int i=2;i<=n;i++)
if(num%i==0)
return false;
return true;
}


十、memset()函数


memset(dp,0,sizeof(dp));  赋值0;
memset(dp,-1,sizeof(dp));  赋值-1
memset(dp,127,sizeof(dp));  赋值很大的数
memset(dp,128,sizeof(dp));赋值很小的数  


十一、填充字符串


1、cout<<setw(n)<<setfill(cc)<<ccc;字符串以长度n输出,不足n前面填充字符cc


2、   
      cout<<ccc;
      cout<<setw(n-ccc.length()-1)<<setfill(cc)<<cc;字符串以长度n输出,不足n后面填充字符cc
      setw()和setfill()只对紧跟在输出后的字符有效果;


3、printf("%05",r)就可以啦,%05d代表输出的数宽度为五位,不足五位前面补0


十二、map(L2)


map<---,---> mapname;


1、后面的---可以是结构体
比如:
struct node1  
{  
    int data;  
    int next;  
} ;
map<int,node1> mapname;
mapname[0].data = 1;
2、insert
mapname.insert(pair<int,sring>(1,"asdf"));
mapname.insert(map<int, string>::value_type (3, "student_three"));  不能覆盖已存在的key的对应的value
3、大小
size()
4、遍历
(1)、正向
map<int, string>::iterator iter = mapname.begin();iter!=mapname.end();iter++;
(2)、反向
map<double,int>::reverse_iterator iter;
for(iter = single.rbegin();iter!=single.rend();iter++){}
(3)、iter
iter->first:key的值
iter->second:value的值


5、查找
find()函数,返回当前位置的迭代器,否则返回结尾的迭代器
6、删除
erase(iter),删除iter位置的元素
erase(iter,iter+5)删除范围的元素(前闭后开集合)
erase(1)根据键值删除元素,删除键值为1 的元素
7、排序
自动按key升序排列
8、其他
     begin()         返回指向map头部的迭代器


     clear()        删除所有元素


     count()         返回指定元素出现的次数


     empty()         如果map为空则返回true


     end()           返回指向map末尾的迭代器
     
     lower_bound()   返回键值>=给定元素的第一个位置


     max_size()      返回可以容纳的最大元素个数


     rbegin()        返回一个指向map尾部的逆向迭代器


     rend()          返回一个指向map头部的逆向迭代器


     size()          返回map中元素的个数


     swap()           交换两个map


     upper_bound()    返回键值>给定元素的第一个位置


     value_comp()     返回比较元素value的函数
9、map可嵌套


10、map<string,double> mapname 输出double时用printf("%lf",***)可以避免输出为int型(我用cout也输出的是double型···)


十三、set(L2)


根据元素键值自动排序,默认升序(从小到大)不允许键值重复


1. begin()--返回指向第一个元素的迭代器


2. clear()--清除所有元素


3. count()--返回某个值元素的个数


4. empty()--如果集合为空,返回true


5. end()--返回指向最后一个元素的迭代器


6. erase()--删除集合中的元素


   erase(it)      ------      删除迭代器it对应的元素


   erase(l, r)      ------      删除迭代器[l, r)之间的元素


7. find()--返回一个指向被查找到元素的迭代器


   find(k)      ------      寻找k,若找到返回对应的迭代器,否则返回end();


8. insert()--在集合中插入元素


   insert(a, b)      ------      插入指针[a, b)之间的元素,已有元素不会再次插入


11. lower_bound()--返回指向大于(或等于)某值的第一个元素的迭代器


12. max_size()--返回集合能容纳的元素的最大限值


13. rbegin()--返回指向集合中最后一个元素的反向迭代器


14. rend()--返回指向集合中第一个元素的反向迭代器


15. size()--集合中元素的数目


16. upper_bound()--返回大于某个值元素的迭代器


17.结构体和set


/*
代码:按着成绩从大到小排序,成绩相同按着学号从小到大输出姓名


num name score
1   aa   1
2   bb   1
3   cc   2 


运行结果
cc
aa

bb

这里也有疑惑,同样是重载运算符为什么score是大到小学号确是小到大?

*/


#include<iostream>
#include<string>
#include<cstdio>
#include<map>
#include<set>
using namespace std; 
struct stu
{
int num;
string name;
int score;
};
//进行比较要重载运算符,可以通过这种方式改变默认排序
bool operator < (const stu&a,const stu&b)
{
if(a.score!=b.score)
return a.score<b.score;
else if(a.score==b.score)
return a.num<b.num;
}
set<stu> s;
int main()
{
stu a,b,c;
a.name = "aa";
a.num = 1;
a.score = 1;
//插入结构体
s.insert(a);
b.name = "bb";
b.num = 2;
b.score = 1;
s.insert(b);
c.name = "cc";
a.num = 3;
a.score = 2;
s.insert(c);

set<stu>::iterator it;
for(it = s.begin();it!=s.end();it++)
{
a = (stu)(*it);//输出内容
cout<<a.name<<endl;
}
return 0;
}


十四、sort比较(L1)


1、
int a[10];
sort(a,a+10);默认是从小到大


2、
bool cmp(int a,int b)
{
return a>b;
}
sort(a,a+10,cmp);从大到小
十五、动态规划(凑零钱)


#include<iostream>
using namespace std;
int main()
{
int coins[3] = {2,3,5};
int money = 8;
int dp[10001] = {0};
int dp2[10001][3] = {0};
/*
下标i是要凑的钱数 
dp[i]是凑够钱数所需的最小硬币数 
dp2[i][j]是凑i时用的coins[j]的个数,用来求各个硬币用了多少 
*/
for(int i=coins[0];i<=money;i++)
{
for(int j=0;j<3;j++)
{
if(coins[j]+coins[0]<=i||coins[j] == i)
{
dp[i] = min(dp[i-coins[0]]+1,dp[i-coins[j]]+1);
/*if(dp[i] == dp[i-coins[0]]+1)
dp2[i][0] = dp2[i-coins[0]][0]+1;
else
dp2[i][j] = dp2[i-coins[j]][j]+1;//这里是错的,本想输出最少钱数都用了哪些钱各多少*/
}
}
}
/*
i 从 coins[0]开始是因为最小的硬币面值是coins[0] ,比coins[0]小的面值凑不出来
j遍历coins数组,比较凑i-coins[j]与i-coins[0]哪个需要的硬币数最少,最后"+1"中的"1"是指coins[i]或者coins[0]这个硬币,最后得到凑i元最小硬币数
if中的条件是:
当i-coins[j]<coins[0]时, i-coins[j]这个面值是无法凑出的,因为 最小的硬币面值是coins[0] ,比coins[0]小的面值凑不出来,所以最后得到的结果一定是错的
所以在 i-coins[j]>=coins[0]时剩下的面值才能被凑出来换句话说只有这时 i-coins[j]才存在非0 最小值,比较才有意义 
另一种情况就是i=coins[j]时,i = 2,j = 0时 2+2<=2这样就不能进循环但是2这个面值是可以凑出来的,所以要添加后面的条件考虑特殊情况 
dp2[i][j] = dp2[i-coins[j]][j]+1;:凑i用的j的最小个数就是凑 i-coins[j]时用的j的最小个数加上1 
*/
cout<<dp[money]<<endl;
cout<<"2: "<<dp2[money][0]<<endl;
cout<<"3: "<<dp2[money][1]<<endl;
cout<<"5: "<<dp2[money][2]<<endl;
return 0;
}


十五、排序算法:见数据结构


十六、并查集:查找源头是否相同
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值