算法拾遗二十四之暴力递归到动态规划二

news2024/11/19 2:18:26

算法拾遗二十四之暴力递归到动态规划二

      • 背包问题一
        • 优化
      • 题目二
        • 优化
      • 题目三(贴纸拼词)
        • 优化
      • 题目四:最长公共子序列
        • 优化

背包问题一

在这里插入图片描述
weights[i]和values[i]的值都是大于等于0的,不存在负数的情况。
可以从尝试入手,改动态规划,常见从左往右依次尝试的模型
在这里插入图片描述
假设有0,1,2三个货物,分别有其重量和价值,我们通过从左往右,0号货物在要的时候【不要的时候】1号货物在要的时候【不要的时候】2号货物在要的时候【不要的时候】,每个分支都走,那么就能找到最大值,因为我们暴力枚举了。

    //所有的货,重量和价值,都在w和v数组里
    //为了方便,其中没有负数
    //bag背包容量,不能超过这个载重
    //返回:不超重的情况下,能够得到的最大价值

    public static int maxValue(int[] w, int[] v, int bag) {
        if (w == null || v == null || w.length != v.length || w.length == 0) {
            return 0;
        }

        //尝试函数
        return process(w, v, 0, bag);
    }

    /**
     * @param w
     * @param v
     * @param index 当前考虑到了index号货物,index及其后面的所有货物都可以自由选择,
     *              返回最大价值,所作的选择不能超过背包容量
     * @param bag
     * @return
     */
    public static int process(int[] w, int[] v, int index, int bag) {
        //bag 不写成<=0是因为可能weight=0但是value!=0
        if (bag < 0) {
            return -1;
        }
        //越界位置,没有货物
        if (index == w.length) {
            return 0;
        }
        // index 没到最后,有货,index位置的货
        // bag有空间
        //不要当前的货,走所有的分支
        int p1 = process(w, v, index + 1, bag);

        //要当前的货,走所有的分支
        int p2 = 0;
        int next = process(w, v, index + 1, bag - w[index]);
        //看是否是一个无效解,要我后续有效才加
        if (next != -1) {
            p2 = v[index] + next;
        }
        return Math.max(p1, p2);
    }

优化

先看暴力递归是否有重复调用,
在这里插入图片描述
w,v 是固定参数,后面两个参数是可变参数,
首先调用p(0,15)
如果要了0,1但是没有要2号传p(3,10)
如果没要0,1但是要了2号同样是传p(3,10)
重复过程就出现了。

再分析可变参数的变化范围
index 0-N
rest(bag的rest):负-bag
建表:
假设有4个货物,bag=10,如下图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
再根据如上代码去推

    public static int dp(int[] w, int[] v, int bag) {
        if (w == null || v == null || w.length != v.length || w.length == 0) {
            return 0;
        }
        int N = w.length;
        //index 0-N
        // rest 假设从0到bag
        int[][] dp = new int[N + 1][bag + 1];
        // 填入dp,看依赖关系
        for (int index = N - 1; index >= 0; index--) {
            for(int rest = 0 ; rest <= bag;rest++) {

                int p1 = dp[index+1][rest];
                int p2 = 0;
                int next = rest -w[index] < 0 ? -1 : dp[index+1][rest-w[index]];
                if(next != -1) {
                    p2 = v[index] + next;
                }
                dp[index][rest] = Math.max(p1,p2);
            }
        }
            return dp[0][bag];
    }

题目二

在这里插入图片描述
在这里插入图片描述
如上图,终止条件返回1,是因为我的0位置做了决定是A,我的1位置做了决定是A,2位置做了决定是A,3位置终止返回1,我前面做了决定将111,转换为AAA,我3位置只是搜集一个点数。

如果做的决定单独遇到了0字符,那么说明前面做的决定是错误的。

  //str只含有数字字符0-9
    //返回多少种转化方案
    public static int number(String str) {
        if (str == null || str.length() == 0) {
            return 0;
        }
        return process(str.toCharArray(), 0);
    }

    //str[0..i-1]转化无需过问
    //str[i...]去转化,返回有多少种转化方法
    public static int process(char[] str, int i) {
        if (i == str.length) {
            return 1;
        }
        //i没到最后,说明有字符
        if (str[i] == '0') {
            return 0;
        }

        //str[i]!='0'我总是可以做一个决定的
        // ,就是让i位置上的字符单转,然后让i+1位置做决定
        //可能性一,i单转
        int ways = process(str, i + 1);
        //可能性二,i位置字符和i+1位置字符共同构成一个字符
        if (i + 1 < str.length && (str[i] - '0') * 10 + str[i + 1] - '0' < 27) {
            //说明后面有字符
            ways+=process(str,i+2);
        }

        return ways;
    }

优化

 public static int dp2(String s) {
        if (s == null || s.length() == 0) {
            return 0;
        }
        char[] str = s.toCharArray();
        int N = str.length;
        int[] dp = new int[N + 1];
        dp[N] = 1;
        for (int i = N - 1; i >= 0; i--) {
            if (str[i] != '0') {
                int ways = dp[i + 1];
                if (i + 1 < str.length && (str[i] - '0') * 10 + str[i + 1] - '0' < 27) {
                    ways += dp[i + 2];
                }
                dp[i] = ways;
            }
        }
        return dp[0];
    }

题目三(贴纸拼词)

本题测试链接:https://leetcode.com/problems/stickers-to-spell-word
在这里插入图片描述
思路:
假设有三种贴纸
“abc”,“bba”,“cck”,
然后要拼成如下串"bbbbaca"
,首先排序"aabbbbc",然后选择贴纸。
第一张贴纸选abc,看最后能有几张,第一张贴纸选bba看最后能有几张贴纸,第一张贴纸选cck,看最后能有几张,因为最终拼成的结果,【答案必在其中,因为肯定有某张贴纸被作为了第一张,所有分支里面最小的那个就是要的结果】
为什么要排序?
为了命中率更高一些

	public static int minStickers1(String[] stickers, String target) {
		int ans = process1(stickers, target);
		//怎么都拼不成target则返回-1
		return ans == Integer.MAX_VALUE ? -1 : ans;
	}

	// 所有贴纸stickers,每一种贴纸都有无穷张
	// target
	// 返回最少张数
	public static int process1(String[] stickers, String target) {
		//如果target没剩下东西了【说明之前的决策都分解完了则还需要0张贴纸】
		if (target.length() == 0) {
			return 0;
		}
		int min = Integer.MAX_VALUE;
		//每一张贴纸都假设是第一张,看target哪些字符能被first搞定,
		// 然后剩下的跑下一个流程
		for (String first : stickers) {
			//每一张贴纸作为第一个串,看还剩下的字符
			String rest = minus(target, first);
			//跑后续的流程
			if (rest.length() != target.length()) {
				min = Math.min(min, process1(stickers, rest));
			}
		}
		//如果min是系统最大值,则不让结果加一否则结果加一(加的是第一张卡片,因为第一张在前面的步骤
		// 中没算进去)
		return min + (min == Integer.MAX_VALUE ? 0 : 1);
	}

	public static String minus(String s1, String s2) {
		char[] str1 = s1.toCharArray();
		char[] str2 = s2.toCharArray();
		int[] count = new int[26];
		for (char cha : str1) {
			count[cha - 'a']++;
		}
		for (char cha : str2) {
			count[cha - 'a']--;
		}
		StringBuilder builder = new StringBuilder();
		for (int i = 0; i < 26; i++) {
			if (count[i] > 0) {
				for (int j = 0; j < count[i]; j++) {
					builder.append((char) (i + 'a'));
				}
			}
		}
		return builder.toString();
	}

说明:
假设有ac和ka两张贴纸,要组成串abc:
在这里插入图片描述
首先选择贴纸ac做第一张,解决了abc里面的ac还剩下一个b,
然后b用ac行吗,发现不行,然后b用ka行吗,发现也不行,返回一个系统最大值回去。
第二步选择ka作为第一张,剩下bc,接下来又用ac行吗,发现不行,b搞不定,用ka行吗,发现还是搞不定b,所以也返回系统最大值回去

优化

假设有如下贴纸:
“acc”,“bbc”,“aaa”
在这里插入图片描述
可以做成一个二维数组将字母对应位置标记为词频次数。这样减起来快。

public static int minStickers2(String[] stickers, String target) {
		int N = stickers.length;
		// 关键优化(用词频表替代贴纸数组)生成词频统计数组
		int[][] counts = new int[N][26];
		for (int i = 0; i < N; i++) {
			char[] str = stickers[i].toCharArray();
			for (char cha : str) {
				counts[i][cha - 'a']++;
			}
		}
		int ans = process2(counts, target);
		return ans == Integer.MAX_VALUE ? -1 : ans;
	}

	// stickers[i] 数组,当初i号贴纸的字符(词频)统计 int[][] stickers -> 所有的贴纸
	// 每一种贴纸都有无穷张
	// 返回搞定target的最少张数
	public static int process2(int[][] stickers, String t) {
		//target0张贴纸
		if (t.length() == 0) {
			return 0;
		}
		// target做出词频统计
		// target  aabbc  2 2 1..
		//                0(a) 1(b) 2(c)..
		char[] target = t.toCharArray();
		int[] tcounts = new int[26];
		for (char cha : target) {
			tcounts[cha - 'a']++;
		}
		int N = stickers.length;
		int min = Integer.MAX_VALUE;
		for (int i = 0; i < N; i++) {
			// 尝试第一张贴纸是谁
			int[] sticker = stickers[i];
			// 最关键的优化(重要的剪枝!这一步也是贪心!)【所有分支中必须含有第一个字符的分支才跑后续流程】
			//举例:有目标串aaabbbck,然后有贴纸bbc,cck,kkb,bab,只有bab能第一次进来,剪枝成立
			//原来我的最优答案可能出现好几回现在我的最优答案可能就只出现一次
			if (sticker[target[0] - 'a'] > 0) {
				StringBuilder builder = new StringBuilder();
				for (int j = 0; j < 26; j++) {
					if (tcounts[j] > 0) {
						int nums = tcounts[j] - sticker[j];
						for (int k = 0; k < nums; k++) {
							builder.append((char) (j + 'a'));
						}
					}
				}
				//剩余字符调下一个流程
				String rest = builder.toString();
				min = Math.min(min, process2(stickers, rest));
			}
		}
		return min + (min == Integer.MAX_VALUE ? 0 : 1);
	}

第三种方法:(由于string t是个可变参数,但是不能将其变为严格表结构,因为不知道target有多少可能性,空间可能都爆掉了)

public static int minStickers3(String[] stickers, String target) {
		int N = stickers.length;
		int[][] counts = new int[N][26];
		for (int i = 0; i < N; i++) {
			char[] str = stickers[i].toCharArray();
			for (char cha : str) {
				counts[i][cha - 'a']++;
			}
		}
		HashMap<String, Integer> dp = new HashMap<>();
		dp.put("", 0);
		int ans = process3(counts, target, dp);
		return ans == Integer.MAX_VALUE ? -1 : ans;
	}

	public static int process3(int[][] stickers, String t, HashMap<String, Integer> dp) {
		//target出现过则直接返回
		if (dp.containsKey(t)) {
			return dp.get(t);
		}
		char[] target = t.toCharArray();
		int[] tcounts = new int[26];
		for (char cha : target) {
			tcounts[cha - 'a']++;
		}
		int N = stickers.length;
		int min = Integer.MAX_VALUE;
		for (int i = 0; i < N; i++) {
			int[] sticker = stickers[i];
			if (sticker[target[0] - 'a'] > 0) {
				StringBuilder builder = new StringBuilder();
				for (int j = 0; j < 26; j++) {
					if (tcounts[j] > 0) {
						int nums = tcounts[j] - sticker[j];
						for (int k = 0; k < nums; k++) {
							builder.append((char) (j + 'a'));
						}
					}
				}
				String rest = builder.toString();
				min = Math.min(min, process3(stickers, rest, dp));
			}
		}
		int ans = min + (min == Integer.MAX_VALUE ? 0 : 1);
		dp.put(t, ans);
		return ans;
	}

题目四:最长公共子序列

https://leetcode.cn/problems/longest-common-subsequence/
常见dp模型:
从左往右尝试模型
范围尝试模型(AB玩家拿牌)
样本对应模型(以样本的结尾作为讨论可能性的基础)
业务限制模型

在这里插入图片描述
假设str1从0到i位置,str2假设从0到j位置,str1和str2的最长公共子序列是多少。
思路:
根据结尾讨论可能性

 public static int longestCommonSubsequence1(String s1, String s2) {
        if (s1 == null || s2 == null || s1.length() == 0 || s2.length() == 0) {
            return 0;
        }
        char[] str1 = s1.toCharArray();
        char[] str2 = s2.toCharArray();
        // 尝试
        return process1(str1, str2, str1.length - 1, str2.length - 1);
    }

    // str1[0...i]和str2[0...j],这个范围上最长公共子序列长度是多少?
    // 可能性分类:
    // a) 最长公共子序列,一定不以str1[i]字符结尾、也一定不以str2[j]字符结尾(a和bc的可能性重叠了,故不写入,省掉一次遍历)
    // b) 最长公共子序列,可能以str1[i]字符结尾、但是一定不以str2[j]字符结尾
    // c) 最长公共子序列,一定不以str1[i]字符结尾、但是可能以str2[j]字符结尾
    // d) 最长公共子序列,必须以str1[i]字符结尾、也必须以str2[j]字符结尾
    // 注意:a)、b)、c)、d)并不是完全互斥的,他们可能会有重叠的情况
    // 但是可以肯定,答案不会超过这四种可能性的范围
    // 那么我们分别来看一下,这几种可能性怎么调用后续的递归。
    // a) 最长公共子序列,一定不以str1[i]字符结尾、也一定不以str2[j]字符结尾
    //    如果是这种情况,那么有没有str1[i]和str2[j]就根本不重要了,因为这两个字符一定没用啊
    //    所以砍掉这两个字符,最长公共子序列 = str1[0...i-1]与str2[0...j-1]的最长公共子序列长度(后续递归)
    // b) 最长公共子序列,可能以str1[i]字符结尾、但是一定不以str2[j]字符结尾
    //    如果是这种情况,那么我们可以确定str2[j]一定没有用,要砍掉;但是str1[i]可能有用,所以要保留
    //    所以,最长公共子序列 = str1[0...i]与str2[0...j-1]的最长公共子序列长度(后续递归)
    // c) 最长公共子序列,一定不以str1[i]字符结尾、但是可能以str2[j]字符结尾
    //    跟上面分析过程类似,最长公共子序列 = str1[0...i-1]与str2[0...j]的最长公共子序列长度(后续递归)
    // d) 最长公共子序列,必须以str1[i]字符结尾、也必须以str2[j]字符结尾
    //    同时可以看到,可能性d)存在的条件,一定是在str1[i] == str2[j]的情况下,才成立的
    //    所以,最长公共子序列总长度 = str1[0...i-1]与str2[0...j-1]的最长公共子序列长度(后续递归) + 1(共同的结尾)
    // 综上,四种情况已经穷尽了所有可能性。四种情况中取最大即可
    // 其中b)、c)一定参与最大值的比较,
    // 当str1[i] == str2[j]时,a)一定比d)小,所以d)参与
    // 当str1[i] != str2[j]时,d)压根不存在,所以a)参与
    // 但是再次注意了!
    // a)是:str1[0...i-1]与str2[0...j-1]的最长公共子序列长度
    // b)是:str1[0...i]与str2[0...j-1]的最长公共子序列长度
    // c)是:str1[0...i-1]与str2[0...j]的最长公共子序列长度
    // a)中str1的范围 < b)中str1的范围,a)中str2的范围 == b)中str2的范围
    // 所以a)不用求也知道,它比不过b)啊,因为有一个样本的范围比b)小啊!
    // a)中str1的范围 == c)中str1的范围,a)中str2的范围 < c)中str2的范围
    // 所以a)不用求也知道,它比不过c)啊,因为有一个样本的范围比c)小啊!
    // 至此,可以知道,a)就是个垃圾,有它没它,都不影响最大值的决策
    // 所以,当str1[i] == str2[j]时,b)、c)、d)中选出最大值
    // 当str1[i] != str2[j]时,b)、c)中选出最大值
    public static int process1(char[] str1, char[] str2, int i, int j) {
        if (i == 0 && j == 0) {
            // str1[0..0]和str2[0..0],都只剩一个字符了
            // 那如果字符相等,公共子序列长度就是1,不相等就是0
            // 这显而易见
            return str1[i] == str2[j] ? 1 : 0;
        } else if (i == 0) {
            // 这里的情况为:
            // str1[0...0]和str2[0...j],str1只剩1个字符了,但是str2不只一个字符
            // 因为str1只剩一个字符了,所以str1[0...0]和str2[0...j]公共子序列最多长度为1
            // 如果str1[0] == str2[j],那么此时相等已经找到了!公共子序列长度就是1,也不可能更大了
            // 如果str1[0] != str2[j],只是此时不相等而已,
            // 那么str2[0...j-1]上有没有字符等于str1[0]呢?不知道,所以递归继续找
            if (str1[i] == str2[j]) {
                return 1;
            } else {
                return process1(str1, str2, i, j - 1);
            }
        } else if (j == 0) {
            // 和上面的else if同理
            // str1[0...i]和str2[0...0],str2只剩1个字符了,但是str1不只一个字符
            // 因为str2只剩一个字符了,所以str1[0...i]和str2[0...0]公共子序列最多长度为1
            // 如果str1[i] == str2[0],那么此时相等已经找到了!公共子序列长度就是1,也不可能更大了
            // 如果str1[i] != str2[0],只是此时不相等而已,
            // 那么str1[0...i-1]上有没有字符等于str2[0]呢?不知道,所以递归继续找
            if (str1[i] == str2[j]) {
                return 1;
            } else {
                return process1(str1, str2, i - 1, j);
            }
        } else { // i != 0 && j != 0
            // 这里的情况为:
            // str1[0...i]和str2[0...i],str1和str2都不只一个字符
            // 看函数开始之前的注释部分
            // p1就是可能性c)
            int p1 = process1(str1, str2, i - 1, j);
            // p2就是可能性b)
            int p2 = process1(str1, str2, i, j - 1);
            // p3就是可能性d),如果可能性d)存在,即str1[i] == str2[j],那么p3就求出来,参与pk
            // 如果可能性d)不存在,即str1[i] != str2[j],那么让p3等于0,然后去参与pk,反正不影响
            int p3 = str1[i] == str2[j] ? (1 + process1(str1, str2, i - 1, j - 1)) : 0;
            return Math.max(p1, Math.max(p2, p3));
        }
    }

优化

改dp:
在这里插入图片描述
有三个依赖:

process1(str1, str2, i, j - 1);
process1(str1, str2, i - 1, j);
process1(str1, str2, i - 1, j - 1)

改出如下dp:

 public static int longestCommonSubsequence3(String s1, String s2) {

        if (s1 == null || s2 == null || s1.length() == 0 || s2.length() == 0) {
            return 0;
        }
        char[] str1 = s1.toCharArray();
        char[] str2 = s2.toCharArray();
        int N = str1.length;
        int M = str2.length;
        int[][] dp = new int[N][M];
        /*
          if (i == 0 && j == 0) {
            return str1[i] == str2[j] ? 1 : 0;
        }
        */
        dp[0][0] = str1[0] == str2[0] ? 1 : 0;
        /*
        else if (i == 0) {
            if (str1[i] == str2[j]) {
                return 1;
            } else {
                return process1(str1, str2, i, j - 1);
            }
         */
        for (int j = 1; j < M; j++) {
            dp[0][j] = str1[0] == str2[j] ? 1 : dp[0][j - 1];
        }
        /*
        else if (j == 0) {
            if (str1[i] == str2[j]) {
                return 1;
            } else {
                return process1(str1, str2, i - 1, j);
            }
        }
         */
        for (int i = 1; i < N; i++) {
            dp[i][0] = str1[i] == str2[0] ? 1 : dp[i - 1][0];

        }

        for (int i = 1; i < N; i++) {

            for (int j = 1; j < M; j++) {

                int p1 = dp[i - 1][j];
                int p2 = dp[i][j - 1];
                int p3 = str1[i] == str2[j] ? (1 + dp[i - 1][j - 1]) : 0;
                dp[i][j] = Math.max(p1, Math.max(p2, p3));
            }

        }
            return dp[N-1][M-1];
    }

总结:当有一个样本做行,另一个样本做列的时候,就用它的结尾组织可能性,【包含上面代码的a,b,c,d四种情况】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/159810.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于智能矿山电力监控系统的设计与应用方法

摘要&#xff1a;随着煤矿建设的智能化程度越来越高&#xff0c;构建智能电力监控系统实现对矿山生产的有效监控至关重要。首先分析了矿山电力监控系统存在的主要问题&#xff0c;其次重点介绍了基于智能矿山电力监控系统的设计过程&#xff0c;后提出了加强智能电力监控系统的…

Inspur KOS 龙蜥衍生版面向智慧新媒体转型的探索与实践 | 龙蜥案例

编者按&#xff1a;日前&#xff0c;龙蜥社区理事单位浪潮信息正式对外发布基于龙蜥操作系统&#xff08;Anolis OS&#xff09;的服务器操作系统 Inspur KOS&#xff0c;并基于 Inspur KOS 推出可视化迁移方案 C2K&#xff0c;该方案能够将用户应用安全可靠地切换到 Inspur KO…

【系列02】Java流程控制 scanner 选择结构 循环结构语句使用 [有目录]

Scanner输入 Next和NextLine区别 NextLine 用的会多点 因为Next遇到空格就断开了 next语法使用 package com.SunAo.scanner; import java.util.Scanner; public class Demo01 {public static void main(String[] args) {//创建扫描器用来接收 键盘输入Scanner scanner new …

李宏毅ML-批次与动量

批次与动量 文章目录批次与动量1. Small batch or Large batch?2. Gradient descent Momentum3. 总结1. Small batch or Large batch? 在使用 gradient descent 进行 optimization 时&#xff0c;在每一次 epoch 前&#xff0c;要 shuffle 所有的资料&#xff0c;然后再分成…

无桌面Centos7系统安装Cypress@9.0.0并运行

一、安装Cypress 安装前准备 1、安装npm 下载安装包 cd /usr/local mkdir node cd node wget https://npm.taobao.org/mirrors/node/v15.8.0/node-v15.8.0-linux-x64.tar.gz ls -l解压这个包 tar -zxvf node-v15.8.0-linux-x64.tar.gz 你会发现已经有一个node的目录解压…

11、Javaweb_JSPMVCELJSTL三层架构用户列表案例

JSP: 1. 指令 * 作用&#xff1a;用于配置JSP页面&#xff0c;导入资源文件 * 格式&#xff1a; <% 指令名称 属性名1属性值1 属性名2属性值2 ... %> * 分类&#xff1a; 1. page &#xff1a; 配置JSP页面的 * content…

①【Spring】一文了解IOC容器

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 一文掌握IOC一、IOC二、IOC容器的实现BeanFact…

一文掌握fastapi微服务开发

目录 一、概述 1.1 微服务 1.1.1 微服务的优势 1.1.2 微服务的缺点 1.2 为何使用Python开发微服务 1.3 FastAPI概述 二、开发 2.1 安装FastAPI 2.1.1 安装虚拟环境 2.1.2 创建虚拟环境 2.1.3 激活虚拟环境 2.1.4 安装FastAPI 2.2 FastAPI简单使用 2.2.1 查询 2.…

java注解以及如何利用反射获取注解的属性值

一、什么是注解 1.Annotation是从JDK5.0开始引入的新技术 2.Annotation的作用 : &#xff08;1&#xff09;不是程序本身&#xff0c;可以对程序作出解释(这一点和注释(comment)没什么区别)&#xff08;2&#xff09;可以被其他程序(比如:编译器等)读取 3.Annotation的格式…

【每日一题】【LeetCode】【第十一天】杨辉三角

解决之路 题目描述 测试案例&#xff08;部分&#xff09; 第一次 杨辉三角感觉还是挺经典的代码题目&#xff1f;之前大一学C语言好像写过一次。 不过&#xff0c;自己当时就不会写&#xff0c;这次自己先试试能不能想出解决方案。 输入数字是几&#xff0c;那就要输出几…

亚马逊云科技帮助Gemsouls在云上快速实现技术验证与部署

元宇宙热度居高不下&#xff0c;它所创造的虚拟世界进一步拉近了人与人之间的距离&#xff0c;用数字化的形式消除地理与空间上的隔阂。而高度拟真化的虚拟人与AI虚拟社交&#xff0c;是元宇宙落地的重要领域&#xff0c;打造以人工智能驱动的虚拟人社交平台已成为行业大势。 …

DNS 的一些基础知识,以及 DNS 转换域名的过程

DNS(Domain Name System)&#xff0c;主要作用是将域名转成 IP&#xff0c;本文主要讲解了 DNS 的一些基础知识&#xff0c;以及 DNS 转换域名的过程。DNS 是什么dig命令绝大多数网络通信都是基于 TCP/IP 协议&#xff0c;而 TCP/IP 协议的基础是 IP&#xff0c;所以网络中的计…

获取未来时间 一年或N年

需求 展示从本月初开始 一年的时间 或N年的时间 以便用户选择思路 一年12个月 是已知的 从本月到12月可以生成本年的每天数据从1月至上月可以生成所需得到最后一年的数据今年加最后一年的月份可拼接一年时间 所以中间年份是所需年分-1的数组数据中间年份都是1-12月 可以通过年份…

软件的生命周期和测试的生命周期的区分

软件的生命周期测试的生命周期软件测试贯穿于软件的整个生命周期在需求分析阶段测试人员的活测试人员需要站在用户角度分析&#xff1a;软件需求是否合理&#xff1b;站在技术角度分析&#xff1a;技术上是否可行&#xff0c;还有没有优化的空间&#xff1b;站在测试角度分析&a…

VALL-E:微软全新语音合成模型可以在3秒内复制任何人的声音

近日&#xff0c;微软研究人员宣布了一种新的语音合成AI模型 VALL-E&#xff0c;给出3秒样音就可以精确地模拟一个人的声音。一旦它学会了一个特定的声音&#xff0c;VALL-E可以复制说话者的情绪和语气&#xff0c;即使说话者本人从未说过的单词也可以模仿。 论文地址&#xf…

xlCompiler转换为程序的优秀工具

xlCompiler转换为程序的优秀工具 xlCompiler是将oxel文件转换为程序的优秀工具。无需担心删除oxel文件中使用的宏和公式。该工具将您所做的转换为Exe可执行文件&#xff0c;这比分发原始文件时要低得多。最终的文件不需要氧气来执行&#xff0c;您也会有一种在简单的氧气环境中…

D. Friendly Spiders(bfs+筛法)

传送门题意&#xff1a;给你n个蜘蛛&#xff0c;每个蜘蛛有自己的腿数&#xff0c;如果某两个蜘蛛可以直接联系&#xff0c;那么这两个蜘蛛的最大公约数就不为1&#xff0c;否则这两只蜘蛛就不能直接联系。现在给你两个蜘蛛的序号i,j问这两只蜘蛛是否可以直接或者通过其他的蜘蛛…

SDK安全专项评测证书

SDK安全专项行动”是中国信息通信研究院安全研究所大数据应用与安全创新实验室共同发起的&#xff0c;实验室紧跟信息技术发展趋势&#xff0c;依托数据安全、移动安全等领域深厚积累&#xff0c;通过前瞻研究和实践探索&#xff0c;形成了完整的SDK评测方案和指标体系。 SDK产…

【HCIA-openEuler】实验手册—05【openEuler软件管理】

文章目录一、实验介绍1、内容描述2、实验目的二、配置Yum源步骤1&#xff1a;进入yum repo目录步骤2&#xff1a;更改openEuler_x86_64.repo文件步骤3&#xff1a;刷新列出软件列表三、使用RPM命令管理软件1、RPM查询命令步骤1&#xff1a;执行以下命令&#xff0c;通过yum和rp…

华为DHCP实验配置

配置AR1为PC2分配地址 dhcp enable ip pool DHCP_PC2 network 192.168.20.200 mask 24 gateway-list 192.168.20.254 dns-list 192.168.20.100 excluded-ip-address 192.168.20.100 int g0/0/1 ip address 192.168.20.254 24 dhcp select global 配置AR1为PC3分配IP地址 dhcp e…