版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/monochrome00/article/details/81462068
题目链接<http://acm.hdu.edu.cn/showproblem.php?pid=6351>
题意:
给你一个数,最多可以进行k次的操作,每次操作可以把某一位数字和另一位数字交换,可以与自己交换(就相当于不交换),问k次操作后能获得的最大值和最小值是多少。
题解:
一开始应该都会考虑贪心,从高位开始,一步步把数值较大的提上来。比如123,把3提上来转化成321。
这就会产生一个问题,如果后面有多位相同的,应该换哪个?比如1233,只换一次,那应该是换最后一个也就变成了3231。把最靠后的最大值换上来应该是最优的。
可是这并不对。比如6299。交换一次变成9296,交换两次变成9926,交换三次变成9962。
可其实也可以这样交换,6299->9269->9962。只需要两次交换就成了最大值。
所以贪心是错的。
但我们也可以发现,唯一能产生错误的原因就是因为后面所找到的最大值有多个的情况,我们就只需把后面的每种情况搜索一遍就行了。
另外可以得出一个结论,任意的m位数,转换成另一个数,所需要的转换次数不超过m-1次.。所以可以直接进行k=min(k,位数)。
我是通过数字实现的,如果用字符串的话会更方便,也会更快。
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<iostream>
using namespace std;
typedef long long ll;
const ll N=1e5+7;
const ll inf=1e5+7;
ll n,k,dn;
ll a[50];
struct Node{
ll x,i,stp;
Node(ll x,ll i,ll stp):x(x),i(i),stp(stp){}
};
ll bfs1(){
queue<Node>q;
q.push(Node(n,dn,0));
ll ans=(ll)1e10;
while(!q.empty()){
Node t=q.front();q.pop();
ans=min(ans,t.x);
if(t.stp==k) continue;
if(t.i==1) continue;
ll tmp=t.x,cnt=0;
while(tmp){
a[++cnt]=tmp%10;
tmp/=10;
}
ll mi=t.i;
for(ll i=t.i-1;i>=1;i--){
if(a[i]==a[t.i]) continue;
if(a[i]==0&&t.i==dn) continue;
if(a[i]<a[mi]) mi=i;
}
if(mi==t.i)
q.push(Node(t.x,t.i-1,t.stp));
else{
for(ll i=t.i-1;i>=1;i--){
if(a[i]==a[mi]){
swap(a[i],a[t.i]);
ll tmp=0;
for(ll j=cnt;j>=1;j--)
tmp=tmp*10+a[j];
q.push(Node(tmp,t.i-1,t.stp+1));
swap(a[i],a[t.i]);
}
}
}
}
return ans;
}
ll bfs2(){
queue<Node>q;
q.push(Node(n,dn,0));
ll ans=0;
while(!q.empty()){
Node t=q.front();q.pop();
ans=max(ans,t.x);
if(t.stp==k) continue;
if(t.i==1) continue;
ll tmp=t.x,cnt=0;
while(tmp){
a[++cnt]=tmp%10;
tmp/=10;
}
ll ma=t.i;
for(ll i=t.i-1;i>=1;i--){
if(a[i]==a[t.i]) continue;
if(a[i]>a[ma]) ma=i;
}
if(ma==t.i)
q.push(Node(t.x,t.i-1,t.stp));
else{
for(ll i=t.i-1;i>=1;i--){
if(a[i]==a[ma]){
swap(a[i],a[t.i]);
ll tmp=0;
for(ll j=cnt;j>=1;j--)
tmp=tmp*10+a[j];
q.push(Node(tmp,t.i-1,t.stp+1));
swap(a[i],a[t.i]);
}
}
}
}
return ans;
}
int main()
{
ll t;
scanf("%lld",&t);
while(t--){
scanf("%lld%lld",&n,&k);
ll tt=n;
dn=0;
while(tt){
dn++;
tt/=10;
}
k=min(k,dn-1);
ll ans1=bfs1();
ll ans2=bfs2();
printf("%lld %lld\n",ans1,ans2);
}
}