程序设计大赛技巧&模板(持续更新)

将要参加的第一个程序设计比赛将近,然而近期生了场病,状态非常不好主要是菜 以至于最近没什么进展,但是身为蒟蒻的我不能放弃学习啊……今天去了趟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;
}

猜你喜欢

转载自blog.csdn.net/weixin_44010678/article/details/87938169