HDU 6351 Beautiful Now DFS+剪枝

Problem Description

Anton has a positive integer n, however, it quite looks like a mess, so he wants to make it beautiful after k swaps of digits.
Let the decimal representation of n as (x1x2⋯xm)10 satisfying that 1≤x1≤9, 0≤xi≤9 (2≤i≤m), which means n=∑mi=1xi10m−i. In each swap, Anton can select two digits xi and xj (1≤i≤j≤m) and then swap them if the integer after this swap has no leading zero.
Could you please tell him the minimum integer and the maximum integer he can obtain after k swaps?

Input

The first line contains one integer T, indicating the number of test cases.
Each of the following T lines describes a test case and contains two space-separated integers n and k.
1≤T≤100, 1≤n,k≤109.

Output

For each test case, print in one line the minimum integer and the maximum integer which are separated by one space.

Sample Input

5

12 1

213 2

998244353 1

998244353 2

998244353 3

Sample Output

12 21

123 321

298944353 998544323

238944359 998544332

233944859 998544332

题意:给出整数n,最多m次交换2个位上的数字,求可能的最小值和最大值

思路:一开始想到了贪心,贪心这个题应该很不好做,后来用DFS+剪枝

1.DFS每一位

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
const int INF = 1e9+5;
int imin,imax,len;
int a[12];
char s[12];

void DFS(int pos,int num,int m)
{
    if(m==0){
        while(pos<=len){
            num=num*10+a[pos];
            pos++;
        }
        imin=min(imin,num);
        imax=max(imax,num);
        return ;
    }
    if(pos==len){
        num=num*10+a[pos];
        imin=min(imin,num);
        imax=max(imax,num);
        return ;
    }
    for(int i=pos;i<=len;i++){
        if(pos==1&&a[i]==0)
            continue ;
        swap(a[pos],a[i]);
        DFS(pos+1,num*10+a[pos],m-1);
        swap(a[pos],a[i]);
    }
    DFS(pos+1,num*10+a[pos],m);
}
int main()
{
    int n,m,t;
    scanf("%d",&t);
    while(t--)
    {
        int num=0;
        scanf("%s %d",&s,&m);
        len=strlen(s);
        for(int i=1;i<=len;i++){
            a[i]=s[i-1]-'0';
            num=num*10+a[i];
        }
        imin=num;
        imax=num;
        DFS(1,0,m);
        printf("%d %d\n",imin,imax);
    }
}

2.DFS每一位,并且分别求最大和最小,若求最小,如果当前位置小于交换位置则完全没有必要交换,之后判断得到的这个数字是否和原先相等,若相等则跳过

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;    
typedef long long ll;
const ll INF = 1e10 + 7;
char str[20], str1[20], str2[20];
int len, bo[10], flag1, flag2, k;
ll ans1,ans2;
ll maxans, minans;
void init()
{
    memset(bo, 0, sizeof(bo));
    maxans = 0;
    for (int i = 0;i < len;i++)
        bo[str[i] - '0']++;
    for (int i = 9;i >= 0;i--)
        while(bo[i]--)maxans = maxans * 10 + i;
    memset(bo, 0, sizeof(bo));
    for (int i = 0;i < len;i++)
        bo[str[i] - '0']++;
    for (int i = 1;i < 10;i++)
        if (bo[i])
        {
            bo[i]--;
            minans = i;
            break;
        }
    for (int i = 0;i < 10;i++)
        while (bo[i]--)minans = minans * 10 + i;
}
ll count(string str)
{
    ll sum=0;
    for (int i = 0;i < len;i++)
        sum = sum * 10 + str[i] - '0';
    return sum;
}
void dfs1(int num, int index)
{
    if (flag1)return;
    if (num == k)return;
    for (int i = index + 1;i < len;i++)
    {
        if (flag1)return;
        if (str1[index] > str1[i])
        {
            if (index == 0 && str1[i] == '0')continue;
            swap(str1[index], str1[i]);
            ans1 = min(ans1, count(str1));
            if (ans1 == minans)flag1 = 1;
            dfs1(num + 1, index+1);
            swap(str1[index], str1[i]);
        }
    }
    if(index len - 1)k = len - 1;
        dfs1(0, 0);
        dfs2(0, 0);
        printf("%lld %lld\n", ans1, ans2);
    }
}

你可能感兴趣的:(ACM_搜索)