SDNU——8题——F - 数字排列

现有n个k位的数字,你的任务是重新安排数字每一位的位置,使得重新安排后这n个数字中最大的数字和最小的数字之差的绝对值最小,对于每一位的调整是相对于所有的数字的,例如有3个数字1234、4321和7890,重新安排的方案是交换第二位和第三位,则3个数字变为1324、4231和7980。
Input
输入包括多组样例,每组样例包括多行。每组样例的第一行包括2个整数n和k,分别代表数字的个数和位数(1 ≤ n, k ≤  8),接下来的的n行包括n个k位的数字,允许调整后的数字有前导0(例如000123代表123)。
Output
每组数据输出一个整数,为调整后最大数字与最小数字之间的最小差值。
Sample Input
3 3
010
909
012
6 4
5237
2753
7523
5723
5327
2537
Sample Output
3
2700
Hint
第二组样例可以将原顺序( 1,2,3,4) 调整为(3,1,4,2),则第二个数字变为5237,第三个数字变为2537,分别为这样变换后的最大值和最小值,可以验证这样变换后的差值2700为最小差值。

#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<memory.h>
using namespace std;
int main()
{	
	int n,k,i,j,l,num,cnt=1;
	int wei[10];
	int ber[30];
	char s[100][100];
	while(cin>>n>>k)
	{
																			//输入数据到二维字符串数组中——方便提取位数
		for(i=1;i<=n;i++) 	cin>>s[i];																//构造一个位数数组[1-k]根据这个数组的排列挑出数据
		for(i=1;i<=k;i++)	wei[i]=i;																		//计算出总共的循环次数~~大循环 
		for(i=2;i<=k;i++)	cnt*=i;
		int ret=9999;																		//遍历大循环 
		for(l=1;l<=cnt;l++)
		{
			
			memset(ber,0,sizeof(ber));
			for(i=1;i<=n;i++)//遍历每一个数 
			{
				for(j=1;j<=k;j++)//遍历位数 
				{
					ber[i]=ber[i]*10+s[i][wei[j]-1]-'0';
				}
			}
			sort(ber+1,ber+1+n);
			ret=min(ret,ber[n]-ber[1]);
			next_permutation(wei+1,wei+1+k);
			
		}
		cout<<ret<<endl;
		
	
	}	
	return 0;
 } 


首先我想到了用二维字符数组去存输入的数据,因为我要对这个数的每一位进行全排列,所以用字符来存每一位数字实现起来方便一些

然后就得想办法全排列了,对于n位数,有 n! 次排列,但是考虑到每一次排列,我就不会了,

所幸,查到stl里有个排序算法啊

next_permutation(wei+1,wei+1+k);

【STL】next_permutation函数用法

转一篇不错的介绍,下面画一下重点

使用方法:next_permutation(数组头地址,数组尾地址);若下一个排列存在,则返回真,如果不存在则返回假

int main()  
{  
    string str = "abcde"; ///输出下5个排列  
    int k = 0;  
    while (next_permutation(str.begin(), str.end()))  
        ///begin()与end()是string类的迭代器  
    {  
        k++;  
        cout << str << endl;  
        if (k == 5)  
        {  
            break;  
        }  
    }  
    return 0;  
注意啊:他这里传的是str.end(),这代表,我定义的char s[][]数组我得给到

next_permutation(wei+1,wei+1+k);
也可以认为这个是左闭右开的//stl里面很多这样的【),所以要指到你想排的最后一个字符的后一位
有了,这个,那么这个题也就轻松的odk了

注意的就是下标问题了~~,

举例:

prev_permutation——求上一个排列



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值