HDU 6351 (带技巧的暴力)
Posted shuaihui520
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 6351 (带技巧的暴力)相关的知识,希望对你有一定的参考价值。
题意:给定一个数,和一个最多交换次数k,问在不超过k次操作的情况,问可以得到的最大值和最小值是多少?
个人解题的艰辛路程 , 开始是想到了暴力枚举的可能 , 打出来发现在判断枚举的数组与原来数组交换了多少次出现了错误 , 我们扫一遍枚举的数组于原来的数组不相同就往后面找到相同 , 但这个是不行的 , 这样必须是每一位数都不一样才可以 , 然后无耻的看了题解 , O!原来是枚举位置 , 然后题解,超时了 , 想了想发现当k>cnt 的时候 ,是一定可以构成出来的 ,不需要枚举 , 所以加了这样Ala
#include<bits/stdc++.h> using namespace std ; int A[20],a[20],T[20],sumMAX[20],sumMIN[20]; int main() { int t; scanf("%d",&t); while(t--) { memset(sumMIN,0,sizeof(sumMIN)); memset(sumMAX,0,sizeof(sumMAX)); int x,k; scanf("%d%d",&x,&k); int cnt=0; while(x) { a[cnt++]=x%10; sumMAX[x%10]++;sumMIN[x%10]++; x/=10; } for(int i=cnt-1 ; i>=0 ; i--) { A[cnt-1-i]=a[i]; } for(int i=0 ; i<cnt ; i++) a[i]=i; int MIN=0x3f3f3f3f,MAX=-1; if(k>=cnt-1)///剪枝 { for(int i=1 ; i<=9 ; i++)///第一位排除0 { if(sumMIN[i]) { printf("%d",i); sumMIN[i]--; break; } } for(int i=0 ; i<=9 ; i++) { while(sumMIN[i]) { printf("%d",i); sumMIN[i]--; } } printf(" "); for(int i=9 ; i>=0 ; i--) { while(sumMAX[i]) { printf("%d",i);sumMAX[i]--; } } puts("");continue; } do { int now=0; int ans=0; if(A[a[0]]==0) continue; for(int i=0 ; i<cnt ; i++) T[i]=a[i]; for(int i=0 ; i<cnt ; i++) { if(T[i]!=i) { now++; if(now>k) break; for(int j=i+1 ; j<cnt ; j++) { if(T[j]==i) { swap(T[i],T[j]);break; } } } if(now>k) break; ans=ans*10+A[a[i]]; } if(now<=k) { // printf("%d %d ",ans,now); MAX=max(MAX,ans) , MIN=min(MIN,ans); } } while(next_permutation(a,a+cnt)); printf("%d %d ",MIN,MAX); } }
以上是关于HDU 6351 (带技巧的暴力)的主要内容,如果未能解决你的问题,请参考以下文章
hdu6351 Beautiful Now (全排列+循环节)
HDU 6351 Beautiful Now(DFS)多校题解