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);
}
}