全排列

\(next\_permutation\)函数

其实就是算从 \([1-n]\) 的所有数的全部的排列可能情况

先看代码

#include<bits/stdc++.h> 
using namespace std;
int main(){  
    int num[3]={1,2,3};
    do  
    {  
        cout<<num[0]<<" "<<num[1]<<" "<<num[2]<<endl; 
    }while(next_permutation(num,num+3)); 
    return 0; 
}  

这个代码输出的为

1 2 3

1 3 2

2 1 3

2 3 1

3 1 2

3 2 1

可以看出,为全排列

当把 \(next\_permutation(num,num+3)\) 改为 \(num+2\),输出就变为了

1 2 3

2 1 3

只针对前两位进行全排列

由此可以看出,\(next\_permutation(num,num+n)\) 函数是对数组 \(num\) 中的前 \(n\) 个元素进行全排列,同时并改变 \(num\) 数组的值。

另外,需要强调的是,\(next\_permutation()\) 在使用前需要对欲排列数组按升序排序,否则只能找出该序列之后的全排列数。

2.运用

\(next\_permutation\) 可以自定义比较函数:

int cmp(char a,char b) {
    if(tolower(a)!=tolower(b))//tolower 是将大写字母转化为小写字母.
        return tolower(a)<tolower(b);
    else return a<b;
}
.
.
.
while(next_permutation(ch,ch+strlen(ch),cmp));

下面是一道例题:

ABC183 \(Travel\)

题意:
\(N\) 个城市,从城市 \(i\) 到城市 \(j\) 需要的时间记为 \(T_{i,j}\)

问从城市 \(1\) 出发,经过所有的其他城市,再回到城市 \(1\),而且每个城市只能走一次。求需要时间正好为 \(K\) 的线路个数。

解法:

根据数据范围,我们可以很轻松的进行全部枚举。

因此,这道题的做法很明显是对地图中数组进行全排列,在枚举过程中,记录当前已经用的时间 \(sum\),如果 \(sum=k\) ,答案就 \(+1\)

代码:

int n,k,mp[10][10],a[10];
int main(){
    cin>>n>>k;
    for(int i=1;i <= n;i++)
        for(int j=1;j <= n;j++)
            cin>>mp[i][j];
    for(int i=1;i <= n;i++) a[i]=i;
    a[n+1]= 1;//让最后一个城市回到城市1
    int ans=0, sum=0;
    do{
        sum=0;
        for(int i=1;i<=n+1;i++) sum += mp[a[i-1]][a[i]];
        if(sum==k)  ans++;
    } while(next_permutation(a+2,a+n+1));//c++的全排列函数,注意要从第二个城市开始
    cout<<ans<<endl;
    return 0;
}
posted @ 2021-10-10 11:28  Evitagen  阅读(41)  评论(0编辑  收藏  举报