c++几个小技巧和小套路思路总结(全排列等)

版权声明:如要转载,请注明出处,谢谢 https://blog.csdn.net/yezonghui/article/details/79475242

一:memset(a,0/false,sizeof(a));

格式:memset(数组名,被赋值的值,数组长度)

也就是要把数组初始化一些值的操作,初始一般可以赋值0或者赋值false;


二:next_permutation函数;

    解释:求一个排序(及某一个序列)的下一个排序的函数--->求下一个序列的规则是按照词典顺序的

   应用:1结合while(next_permutation(a,a+n)(n指序列有n个数)可以输出此时序列后面的所有词典序列;

           2.若当前序列为词典里最小最初最低的那个序列,则可以输出一个全排列。(可以借鉴解决其它遍历问题)

   内部原因:while(next_permutation(a,a+3)),如果存在a之后的排列,就返回true。如果a是最后一个排列,即字典里面没有后继,则返回false。

    代码实例:

do
{                                  //这种结构能够输出全排列。
    cout<<a[0]<<a[1]<<a[2]<<endl;
 }while(next_permutation(a,a+3);

     完整代码实例(输出5个数的全排列)

#include<bits/stdc++.h>
using namespace std;
int main()
{

int a[5],i;
for(i=0;i<5;i++)
{
	cin>>a[i];
 } 
 sort(a,a+5);
 do
 {
 	for(i=0;i<5;i++)
 	{
 		cout<<a[i]<<" ";
	 }
	 cout<<endl;
 }while(next_permutation(a,a+5));
 return 0;
}

      相关扩展:讲到了next_permutation,同时说明也稍微涉及到了全排列,在这里我们就不得不详细总结一下全排列,

因为全排列确实太重要了,对于暴力枚举,对于遍历,甚至一些搜索的题型我们有时使用全排列会简化我们的思路,独辟蹊径。这里就直接上题了。

/*/*要想差值尽量小,两个数的位数最多相差一
(偶数时相等,奇数个时相差一)
1.dfs搜索。 */
/*input:
1
0 1 2 4 6 7
output:
28*/
/*题目大意:先输入一个数字n表示有n组测试用例,接着输入n行数,
每行数一回车表示结束,每行有n个字符,每个字符以空格分开
要求输出每行组出两个数,使得两个数的差值最小*/

答案一(这里是在讲全排列我们就用全排列的方法)(后面还有一种DFS方法)

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[20];
int minss=100000;
int main()
{
	int mins;
	int n,i,j,k=0;
	cin>>n;
	getchar();
	while(n--)
	{
		int len=0,sum1=0,sum2=0,k=0;
		char x;
	//	cin>>x;
	//	while(x!='\n')
	    while((x=getchar())!='\n')
		{
			if(x!=' ')
			a[k++]=x-'0';
		}
		len=k;
		if(len==1)
		cout<<a[0];
		if(len==2)
		cout<<abs(a[0]-a[1]);
		if(len>2)
		{
			sort(a,a+len);
			while(a[0]==0)
			next_permutation(a,a+len);
			int mid=(len+1)/2;
			mins=minss;
			do
			{
				if(a[mid]!=0)
				{
					sum1=sum2=0;
					for(i=0;i<mid;i++)
				sum1=sum1*10+a[i];
				for(i=mid;i<len;i++)
				sum2=sum2*10+a[i];
				mins=min(abs(sum1-sum2),mins);
				}
				
			}while(next_permutation(a,a+len));
			cout<<mins<<endl;
		}
	} //1.注意几点:数组首元素为0时会有影响;2,对于while(n--)要记得一些变量每次都要进行初始化;
 } 
三:与next_permutation完全相反的还有prev_permutation

    功能刚好完全相反,pre函数默认的是从大到小的顺序,next默认是小到大的顺序。

四:接着上面的全排列,我们这再接着加一道全排列的题目(当然这道题后面也可以使用DFS解答,后续再说)

/*题目:

今天是阴历七月初五,acm队员zb的生日。zb正在和C小加、never在武汉集训。他想给这两位兄弟买点什么庆祝生日,
经过调查,zb发现C小加和 never都很喜欢吃西瓜,而且一吃就是一堆的那种,zb立刻下定决心买了一堆西瓜。
当他准备把西瓜送给C小加和never的时候,遇到了一个难 题,never和C小加不在一块住,只能把西瓜分成两堆给他们,
为了对每个人都公平,他想让两堆的重量之差最小。每个西瓜的重量已知,你能帮帮他么?

输入:

多组测试数据(<=1500)。数据以EOF结尾
第一行输入西瓜数量N (1 ≤ N ≤ 20)
第二行有N个数,W1, …, Wn (1 ≤ Wi ≤ 10000)分别代表每个西瓜的重量

输出:

输出分成两堆后的质量差

样例输入:

5

5 8 13 27 14

样例输出:

3*/
使用全排列的答案如下:
#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
int main()
{
	int n,a[100],i,mins=10000,sum1=0,sum2=0;
	cin>>n;
	for(i=0;i<n;i++)
	{
		cin>>a[i];
	}
	sort(a,a+n);
	while(a[0]==0)
	next_permutation(a,a+n);
	int mid=(n+1)/2; 
	do
	{
		sum1=sum2=0;
	//	mins=10000;
		if(a[mid]!=0)
		{
			for(i=0;i<mid;i++)
			sum1+=a[i];
			for(i=mid;i<n;i++)
			sum2+=a[i];
			mins=min(mins,abs(sum1-sum2));
		}
		
	}while(next_permutation(a,a+n));
	cout<<mins<<endl;
	return 0;
}



















猜你喜欢

转载自blog.csdn.net/yezonghui/article/details/79475242