2022-5-22 笔试真题练习

多多的数字组合

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 256M,其他语言512M

多多君最近在研究某种数字组合:
定义为:每个数字的十进制表示中(0~9),每个数位各不相同且各个数位之和等于N。
满足条件的数字可能很多,找到其中的最小值即可。
多多君还有很多研究课题,于是多多君找到了你--未来的计算机科学家寻求帮助。
 
数据范围: 
进阶:空间复杂度  ,时间复杂度 

输入描述:
共一行,一个正整数N,如题意所示,表示组合中数字不同数位之和。
(1 <= N <= 1,000)

输出描述:
共一行,一个整数,表示该组合中的最小值。
如果组合中没有任何符合条件的数字,那么输出-1即可。

 1 import java.util.*;
 2 public class Main{
 3     static int ans;
 4     static boolean f;
 5     public static void main(String[] args){
 6         Scanner sc=new Scanner(System.in);
 7         int n=sc.nextInt();
 8         List<Integer> res=new ArrayList<>();
 9         Set<Integer> set=new HashSet<>();
10         f=false;
11         ans=Integer.MAX_VALUE;
12         dfs(0,n,res,set);
13         // 找到一组互不相同的数字 使得和为n
14         // 0不会使得变化 加进去 肯定放在最前面 直接不考虑0
15         if (f){
16             System.out.print(ans);
17         }else{
18             System.out.print(-1);
19         }
20     }
21     
22     public static void dfs(int sum,int target,List<Integer> res,Set<Integer> set){
23         if (sum>target) return;
24         if (sum==target){
25             StringBuffer sb=new StringBuffer();
26             for (int i:res){
27                 sb.append(i);
28             }
29             ans=Math.min(ans,Integer.parseInt(sb.toString()));
30             f=true;
31             return;
32         }
33         for (int i=1;i<=9;i++){
34             if (!set.contains(i)){
35                 set.add(i);
36                 res.add(i);
37                 dfs(sum+i,target,res,set);
38                 set.remove(i);
39                 res.remove(res.size()-1);
40             }
41         }
42     }
43 }

思路:dfs深度搜索所有可能性。如果穷举需要1~9876543210,会超时。

 

多多的字符变换

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 256M,其他语言512M

多多君最近在研究字符串之间的变换,可以对字符串进行若干次变换操作:

  1. 交换任意两个相邻的字符,代价为0。
  2. 将任意一个字符a修改成字符b,代价为 |a - b|(绝对值)。
现在有两个长度相同的字符串X和Y,多多君想知道,如果要将X和Y变成两个一样的字符串,需要的最少的代价之和是多少。
 

输入描述:
共三行,第一行,一个整数N,表示字符串的长度。
(1 <= N <= 2,000)
接下来两行,每行分别是一个字符串,表示字符串X和Y。
(字符串中仅包含小写字母)

输出描述:
共一行,一个整数,表示将X和Y变换成一样的字符串需要的最小的总代价。

 1 import java.util.*;
 2 public class Main{
 3     public static void main(String[] args){
 4         Scanner sc=new Scanner(System.in);
 5         int n=sc.nextInt();
 6         sc.nextLine();
 7         String a=sc.nextLine();
 8         String b=sc.nextLine();
 9         int[] cnt1=new int[26];
10         int[] cnt2=new int[26];
11         for (int i=0;i<n;i++){
12             char c1=a.charAt(i);
13             char c2=b.charAt(i);
14             cnt1[c1-'a']++;
15             cnt2[c2-'a']++;
16         }
17         for (int i=0;i<26;i++){
18             int t=Math.min(cnt1[i],cnt2[i]);
19             cnt1[i]-=t;
20             cnt2[i]-=t;
21         }
22         int sum=0;
23         int p=0;
24         for (int i=0;i<26;i++){
25             while (cnt2[i]!=0){
26                 while (cnt1[p]==0) p++;
27                 int t=Math.min(cnt1[p],cnt2[i]);
28                 sum+=t*Math.abs(p-i);
29                 cnt1[p]-=t;
30                 cnt2[i]-=t;
31                 // 如果cnt2==0 直接结束
32                 // 
33             }
34         }
35         System.out.print(sum);
36     }
37 }

思路:交换字符的代价为0,所以相同的字符总是可以通过交换使得代价为0。剩下的字符从匹配串开始升序遍历,最优的总是优先匹配前面的代价最小(贪心)

比如 a c 需要匹配d    虽然c到d代价较小,但是d后面的字符匹配a会更大。

posted on 2022-05-22 15:42  阿ming  阅读(66)  评论(0编辑  收藏  举报

导航