数据交换
来源
2018杭电多校第五场
题意
给你一个正整数 ,你可以把
的第
位数字与第
位数字进行交换,
,请注意题目允许自己和自己交换),但是交换过程中不能出现前导零,(例如:11011,第1位和第3位不能交换,因为交换后会出现前导零,输入中保证没有前导零)。现在请你算出经过
次交换后可以得到的最小的整数和最大的整数。
思路
直接利用next_permutation算法进行枚举,复杂度是 ,更新每次的最大值和最小值,由于
,这个计算量还是很大,要通过交换的次数是否超过
剪枝,又通过直接判定
再剪枝。
WA点
杭电C++会T,G++就能过,什么神仙编译器。。。。
特别注意前导0的存在。
数组尽量开小点,bool int也可以稍微加速。
另一种思路
对于每一位,搜索后面的数的最大值/最小值是否有大于/小于自己的,有就交换,这样理论复杂度只有 ,但是总代码量其实差不多。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
const int maxn = 10;
bool vis[maxn];
int bit[maxn], id[maxn];
char s[maxn];
int k, len;
inline bool check() {
memset(vis,0,sizeof(vis));
int cnt=0;
for(int i=0;i<len;i++) {
if(!vis[i]) {
int t=-1;
while(!vis[i]) {
t++;
vis[i]=1;
i=id[i];
}
cnt+=t;
if(cnt>k) return false;
}
}
return true;
}
int cmp(int a, int b) {
return a>b;
}
int main() {
int t; scanf("%d",&t);
while(t--) {
scanf("%s",s);
scanf("%d",&k);
len=strlen(s);
for(int i=0;i<len;i++) {
bit[i]=s[i]-'0';
id[i]=i;
}
if(k>=len) {
sort(bit,bit+len);
int pos=0; while(bit[pos]==0) pos++;
if(bit[0]==0) swap(bit[0],bit[pos]);
for(int i=0;i<len;i++) printf("%d",bit[i]); printf(" ");
sort(bit,bit+len,cmp);
for(int i=0;i<len;i++) printf("%d",bit[i]); printf("\n");
continue;
}
int mi=2e9, mx=-1;
do {
if(bit[id[0]] && check()) {
int temp=0;
for(int i=0;i<len;i++) {
temp=temp*10+bit[id[i]];
}
mi=min(mi,temp);
mx=max(mx,temp);
}
} while(next_permutation(id,id+len));
printf("%d %d\n",mi,mx);
}
}
查看13道真题和解析