1. 程式人生 > >HDU 6351 Beautiful Now DFS+剪枝

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 <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <set>
#include <cmath>
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 <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <cstdio>
#include <fstream>
#include <string>
#include <bitset>

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)dfs1(num, index + 1);
}

void dfs2(int num, int index)
{
    if (flag2)return;
    if (num == k)return;
    for (int i = index + 1;i < len;i++)
    {
        if (flag2)return;
        if (str2[index] < str2[i])
        {
            swap(str2[index], str2[i]);
            ans2 = max(ans2, count(str2));
            //cout <<num<<" "<< ans2 << endl;
            if (ans2 == maxans)flag2 = 1;
            dfs2(num + 1, index+1);
            swap(str2[index], str2[i]);
        }
    }
    if(index<len)dfs2(num, index + 1);
}
int main()
{
    int t;
    char ch;
    scanf("%d", &t);
    while (t--)
    {
        flag1 = flag2 = 0;
        memset(bo, 0, sizeof(bo));
        scanf("%s%d", str, &k);
        len = strlen(str);
        strcpy(str1,str);
        strcpy(str2,str);
        ans1 = ans2 = count(str);
        init();
        if (k > len - 1)k = len - 1;
        dfs1(0, 0);
        dfs2(0, 0);
        printf("%lld %lld\n", ans1, ans2);
    }
}