HDU 6351 Beautiful Now(DFS)多校题解

思路:一开始对k没有理解好,k是指最多k次,不需要达到。这道题dfs暴力就行,我们按照全排列最大最小去找每一位应该和后面哪一位交换。k = 0没判断好WA了2发...

如果k >= len - 1,那么最大最小就是直接sort非前导零的答案。如果k < len - 1,那么我们交换肯定从最大位数交换,比如现在求最大值,那么我们从第一位依次判断,如果该位不是他后面最大的,那么就和后面最大的交换(如果最大的有多个,那么就每个都搜索一下),否则不消耗交换次数判断下一位。最小同理

注意前导零。

代码:

#include<cstdio>
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<vector>
#include<queue>
#include<cstring>
#include<string>
#include<sstream>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 100+10;
const int INF = 0x3f3f3f3f;
int bit[12];
ll pos,k,Max,Min;
ll MIN[12],MAX[12];
ll get_num(int a[]){
    ll ans = 0;
    for(int i = 1;i <= pos;i++){
        ans  = ans * 10 + a[i];
    }
    return ans;
}
void dfs_max(int a[],int rt,int tim){
    if(tim == k){
        Max = max(Max,get_num(a));
        return;
    }
    if(rt == pos){
        Max = max(Max,get_num(a));
        return;
    }
    if(a[rt] == MAX[rt]){
        Max = max(Max,get_num(a));
        dfs_max(a,rt + 1,tim);
    }
    else{
        for(int i = rt + 1;i <= pos;i++){
            if(a[i] != MAX[rt]) continue;
            swap(a[rt],a[i]);
            Max = max(Max,get_num(a));
            dfs_max(a,rt + 1,tim + 1);
            swap(a[rt],a[i]);
        }
    }

}
void dfs_min(int a[],int rt,int tim){
    if(tim == k){
        Min = min(Min,get_num(a));
        return;
    }
    if(rt == pos){
        Min = min(Min,get_num(a));
        return;
    }
    if(a[rt] == MIN[rt]){
        Min = min(Min,get_num(a));
        dfs_min(a,rt + 1,tim);
    }
    else{
        for(int i = rt + 1;i <= pos;i++){
            if(a[i] != MIN[rt]) continue;
            swap(a[rt],a[i]);
            Min = min(Min,get_num(a));
            dfs_min(a,rt + 1,tim + 1);
            swap(a[rt],a[i]);
        }
    }

}
int main(){
    int T;
    char n[12];
    scanf("%d",&T);
    while(T--){
        scanf("%s%d",n,&k);
        pos = strlen(n);
        for(int i = 0;i < pos;i++){
            bit[i + 1] = n[i] - ‘0‘;
        }
        for(int i = 1;i <= pos;i++){
            MIN[i] = bit[i];
        }
        sort(MIN + 1,MIN + pos + 1);
        for(int i = 1;i <= pos;i++){
            MAX[i] = MIN[pos - i + 1];
        }
        if(MIN[1] == 0){
            int p = 2;
            while(MIN[p] == 0){
                p++;
            }
            swap(MIN[1],MIN[p]);
        }
        Max = 0,Min = INF;
        k = min(k,pos - 1);
        dfs_max(bit,1,0);
        dfs_min(bit,1,0);
        printf("%lld %lld\n",Min,Max);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/KirinSB/p/9488342.html

时间: 2024-11-08 00:53:36

HDU 6351 Beautiful Now(DFS)多校题解的相关文章

HDU 2553 N皇后问题(详细题解)

这是一道深搜题目!问题的关键是在剪枝. 下面我们对问题进行分析: 1.一行只能放一个皇后,所以我们一旦确定此处可以放皇后,那么该行就只能放一个皇后,下面的就不要再搜了. 2.每一列只能放一个皇后,所以我们下次搜索就不要再搜已经放过的皇后了. 3.斜的45°线也只能放一个. 综上如何才能最快速的确定一列和45°是否用过这个是个关键步骤,一旦此步骤确定我们就可以很快的进行搜索了. 我们用三个数组来保存他的每一个状态及(三个方向 ↑ ) 但是如果我们保存↑(每一列方向上的皇后)是非常容易保存的 但是保

hdu 4601 Letter Tree 2013多校1-2

不容易啊..一个小错误让我wa死了,找了一个晚上,怎么都找不到 最后是对拍代码找到的错误,发现当步数比较小的时候答案就是对的,比较大的时候就不对了 想到一定是什么地方越界了... power[i] = (i64)(power[i - 1] * 26) % mod; 就是这行... 改成  power[i] = ((i64)power[i - 1] * 26) % mod; 就过了... 这道题总的来说就是非常综合,什么方面都涉及一点,核心部分还是把树转化成序列之后二分边界+RMQ,用dfn来确定

HDU 4920(杭电多校训练#5 1010 题) Matrix multiplication(不知道该挂个什么帽子。。。)

题目地址:HDU 4920 对这个题简直无语到极点...居然O(n^3)的复杂度能过....方法有三.. 1:进行输入优化和输出优化..(前提是你的输入优化不能太搓...) 2:利用缓存优化..详情请看该论文.大体就是将后两个for循环换过来,让坐标改变的频率降下来. 3:叉姐题解中说的正规方法..利用biset存储,进行预处理..(其实我还没看懂.. 我只写了个第二种...代码如下,共勉..神奇的小代码.. #include <iostream> #include <cstdio>

HDU 4864 Task(2014多校--贪心)

Task 比赛当时思路想的差不多,感觉能过的,该处理的也都处理到了,最后还是没过,可能是二分写错了吧-.- 大意:给你n个机器,m个要完成的任务,每个机器跟任务都有两个属性,机器是最大工作时间跟等级,任务是需要工作的时间跟等级.完成一个任务可以得到500*(工作时间)+2*(等级)的报酬.完成任务的条件是机器的工作时间满足任务的需要,等级要大于等于任务的等级,一个机器只能用一次,一个任务也只能用一个机器去完成.需要进行策略选择,使得完成更多的任务. 思路:开始想的就是贪心,也想到了贪心的时候时间

hdu 1501 Zipper (dfs+记忆化搜索)

Zipper Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6491    Accepted Submission(s): 2341 Problem Description Given three strings, you are to determine whether the third string can be formed

hdu 1518 Square (dfs搜索可参考poj1011)

Square Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 8589    Accepted Submission(s): 2784 Problem Description Given a set of sticks of various lengths, is it possible to join them end-to-end

HDU 4940(杭电多校#7 1006) Destroy Transportation system(瞎搞)

题目地址:HDU 4940 当时这个题一看就看出来了是网络流的最小割,然后就一直在想建图..然后突然发现,应该要让T集合的数目最少,不然只要有两个,那这两个的每一个都可以跑到S集合,使得T集合变小.那就只能是1个了.然后..枚举就好了..但是虽然觉得这么做肯定没错..但是不敢敲..因为当时都3个小时了才只有10个队过了...后来又想了几遍后觉得这样没错,就写完交上了.果然AC... 代码如下: #include <iostream> #include <cstdio> #inclu

HDU Redraw Beautiful Drawings 判断最大流是否唯一解

点击打开链接 Redraw Beautiful Drawings Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1660    Accepted Submission(s): 357 Problem Description Alice and Bob are playing together. Alice is crazy about

HDU 1166 敌兵布阵 Segment Tree题解

本题是最基本的分段树操作了.或者一般叫线段树,不过好像和线段没什么关系,只是分段了. 不使用lazy标志,更新只是更新单点. 如果不使用分段树,那么更新时间效率只需要O(1),使用分段树更新效率就需要O(lgn)了. 但是不是用分段树,那么查询的时间效率是O(n),而分段树查询效率是O(lgn) 这就是amortize分摊了时间,而且lgn真的很快,数据不是非常巨大的时候,接近常数了. 故此本题需要使用分段树. #include <cstdio> class EnemyInfo { stati