将要参加的第一个程序设计比赛将近,然而近期生了场病,状态非常不好主要是菜 以至于最近没什么进展,但是身为蒟蒻的我不能放弃学习啊……今天去了趟tanghai的医院,坐公交的时候想了一下,根据自己的理解和经验总结了一下题目中的一些技巧和模板。 也希望各位大佬有其他的好技巧也能够分享一下。
技巧篇
1、char类型的数字转化为int:
string a='2',int b=a-'0';这样就把char类型的1转化为了int型的1
2、int型转char:
在c++11中有专门的函数to_string实现。
int a = 123; string b = to_string(a);即可以转化
但是蓝桥杯中不支持c++11有点不理解为什么蓝桥杯不让用c++11. ,也可以用以下办法解决:
int a=123;
string s,temp;
stringstream ss;
ss<<a;
while(ss>>s)
temp+=s;//temp就是转化完的string型的123
3、sstream
可以用来去除字符串中的空格
string a="a b c d";
string s,temp;
stringstream ss;
ss<<a;
while(ss>>s)
temp+=s;//temp为abcd,去掉了空格
例题:反转字符串中的单词
4、reverse()函数:
可以将字符串反转。
string a="abcde";
reverse(s.begin(),s.end());
cout<<a<<endl;//转化为了edcba。
5、substr()函数:
可以随意随处字符串的一部分
string a="abcde";
cout<<a.substr(1,2);//取出a[1]和a[2],输出字符串bc。
6、next_permutation()函数
利用next_permutation()函数可进行全排列。
例子:
有四张卡片,每张卡片上都有一个数字(数字可能相同)用这四张卡片可以排成很多不同的4位数。按从小到大的顺序输出这些4位数。
输入:1 1 2 3
输出:1123 1132 1213 1231 1312 1321 2113 2131 2311 3112 3121 3211
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a[9];
int n;
for(int i=0;i<4;i++)
{
cin>>n;
a[i]=n;
}
sort(a,a+4);
do
{
for(int i=0;i<4;i++)
cout<<a[i];
cout<<" ";
}while(next_permutation(a,a+4));
}
是不是好简单……。
7、位运算
位运算是个很强大的工具,作为蒟蒻的我都能感受到它的强大,就知道它有多强大了。
按位与(&)通常可以来求二进制中1的个数。
比如这道题:二进制表示中质数个计算置位
按位异或: a ^ a=0; 0 ^ a=a;
比如这道题:只出现一次的数字
还有通过^可以转换大小写字母
'a'^32='A'
'A'^32='a'
模板篇
深度优先搜索(dfs)模板
void dfs(step)
{
if(终止条件)
{
return;
}
if(越界或者是不符合法状态)
return;
for(扩展方式)
{
if(扩展方式所达到状态合法)
{
....//根据题意来添加
标记;
dfs();
修改(剪枝);
(还原标记);
//根据题意确定是否还原标记
//若有标记采用回溯法
}
}
}
一维:
#include<bits/stdc++.h>
using namespace std;
int book[1000],a[1000];//数组根据实际情况定
int n,m;
void dfs(int num)
{
if(num==m+1)//停止条件(这里是举得一个小例子)
{
for(int i=1;i<=m;i++)
cout<<a[i];
cout<<endl;
return ;
}
for(int i=n;i>=1;i--)
{
if(book[i]==0&&i<a[num-1])
{
a[num]=i;
book[i]=1;//标记
dfs(num+1);
book[i]=0;//回溯
}
}
}
int main()
{
//根据实际情况定
dfs(1);
return 0;
}
模板题:组合数
二维:
以水池数目为主。
#include<iostream>
using namespace std;
int a[101][101];
int m,n;
int b[4][2]={1,0,-1,0,0,1,0,-1};
void dfs(int x,int y)
{
if(x>=1&&x<=m&&y>=1&&y<=n&&a[x][y]==1)
{
a[x][y]=0;
for(int i=0;i<4;i++)
{
int tx=x+b[i][0];
int ty=y+b[i][1];
dfs(tx,ty);
}
}
}
int main()
{
int N;
cin>>N;
while(N--)
{
int count=0;
cin>>m>>n;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
cin>>a[i][j];
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
{
if(a[i][j]==1)
{
dfs(i,j);
count++;
}
}
cout<<count<<endl;
}
return 0;
}
广度优先搜索(bfs)模板
bfs是基于队列实现的,通常来解决一些最短路径、最短时间的题。
模板题:Catch My Pet
#include<iostream>
#include<queue>
using namespace std;
struct times
{
int x;
int time;
times(int xx,int time1):x(xx),time(time1){}//结构体内部构造函数
};
int book[100000];//用来标记是否走过该地方
void bfs(int n,int k)
{
queue<times>q;
q.push(times(n,0));
book[n]=1;//走过的地方标记为1
while(!q.empty())
{
times b=q.front();
if(b.x==k)
{
cout<<b.time<<endl;
return ;
}
else
{
//用三种方式进行搜索
if(b.x-1>=0&&!book[b.x-1])
{
q.push(times(b.x-1,b.time+1));
book[b.x-1]=1;
}
if(b.x+1<=100000&&!book[b.x+1])
{
q.push(times(b.x+1,b.time+1));
book[b.x+1]=1;
}
if(b.x*2<=100000&&!book[b.x*2])
{
q.push(times(b.x*2,b.time+1));
book[b.x*2]=1;
}
q.pop();
}
}
}
int main()
{
int n,k;
cin>>n>>k;
bfs(n,k);
return 0;
}
前两天做了一道优先队列+bfs的题目,想了一下午最后百度、问的大佬 才做出来,可以加深对bfs的理解:小明的养生茶
二分查找模板
模板一:当区间[l, r]的更新操作是r = mid; l = mid + 1;时,计算mid时不需要加1。
int bsearch_1(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
}
模板二:
当区间[l, r]的更新操作是r = mid - 1; l = mid;时,计算mid时需要加1。
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
说实话这两种模板卡了我好久。
模板题:Sqrt(x)、H指数Ⅱ。
01背包问题模板
模板题:
题目描述: 辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”
如果你是辰辰,你能完成这个任务吗?
- 输入:第一行有2个整数T(1≤T≤1000)和M(1≤M≤100),用一个空格隔开,T代表总共能够用来采药的时间,M代表山洞里的草药的数目。
接下来的M行每行包括两个在1到100之间(包括1和100)的整数,分别表示采摘某株草药的时间和这株草药的价值。 - 输出:1个整数,表示在规定的时间内可以采到的草药的最大总价值。
- 示例:
输入:
70 3
71 100
69 1
1 2
输出:
3
#include<iostream>
using namespace std;
int t[1000], v[100],B[1000];
int main()
{
int T,m;
cin>>T>>m;
for(int i=1;i<=m;i++)
cin>>t[i]>>v[i];
for(int i=1;i<=m;i++)
for(int j=T;j>=0;j--)
{
if(j>=t[i])
B[j]=max(B[j-t[i]]+v[i],B[j]);
}
cout<<B[T];
return 0;
}
多重背包模板
#include<iostream>
using namespace std;
int t[100000], v[1000000],B[1000000];
int main()
{
int T,m;
cin>>T>>m;
for(int i=1;i<=m;i++)
cin>>t[i]>>v[i];
for(int i=1;i<=m;i++)
for(int j=t[i];j<=T;j++)
{
if(j>=t[i])
B[j]=max(B[j-t[i]]+v[i],B[j]);
}
cout<<B[T];
return 0;
}