<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      0005 ALGO1003-禮物

      問題描述

      試題 算法訓練 禮物
      image

      原始解法(暴力超時)

      最簡單也最容易想到保證超時,bushi的就是暴力解法:從頭遍歷到尾部,每次檢驗可以帶走的石頭數量,可帶走更多則更新。不出意外的超時了,就過了倆 case。

      import java.util.Scanner;
      
      /**
       * @author HuaWang135608
       * @date 2023.03.14 12:28:36
       * @description [試題 算法訓練 禮物](http://lx.lanqiao.cn/problem.page?gpid=T2990)
       */
      
      public class A1003_Present {
      
      	public static void main(String[] args) {
      		try (Scanner sc = new Scanner(System.in)) {
      			// 數據輸入
      			int src_n = sc.nextInt();
      			long src_s = sc.nextLong();
      			int[] src = new int[src_n];
      			for (int i=0; i<src_n; ++i) {
      				src[i] = sc.nextInt();
      			}
      			
      			// 數據處理
      			int res = solve(src, src_s);
      			
      			// 結果輸出
      			System.out.println(res);
      		}
      	}
      	
      	/**
      	 * 暴力解法,從頭遍歷到尾部,每次檢驗可以帶走的石頭數量,可帶走更多則更新
      	 * @param stones 石頭重量數組
      	 * @param S 最大的石頭重量
      	 * @return 可以帶走的最大石頭數量
      	 */
      	public static int solve(int[] stones, long S) {
      		int num = 0;
      		for (int i=0; i+num<stones.length; ++i) {
      			long s = S;
      			int n = 0;
      			// 從當前石頭出發,最多可以帶走多少石頭(結果為 n 個)
      			// j + n < length 
      			// 代表若從當前出發,帶走 n 個 石頭后,若剩余不足 n 個石頭則不用繼續增加
      			for (int j=i; j+n<stones.length; ++j) {
      				s -= stones[j];
      				if (s >= 0) {
      					++n;
      				} else {
      					break;
      				}
      			}
      			// 判斷后 n 個石頭的重量
      			s = 0;
      			int rear = i + (n << 1);
      			for (int j=i+n; j<rear; ++j) {
      				s += stones[j];
      			}
      			// 若后 n 個石頭重量大于可以攜帶的重量
      			while (s > S) {
      				s = s + stones[i + (--n)]; // 前移曾加 1 個
      				s -= stones[--rear] + stones[--rear]; // 前移丟掉 2 個 
      			}
      			if (rear - i > num) { // 若當前可攜帶量大于已有的最優結果,則更新
      				num = rear - i;
      			}
      		}
      		return num;
      	}
      	
      }
      

      改進解法(內存超限)

      一番Ctrl C V思考之后,暴力解法存在很多重復計算,時間復雜度來到 \(O(KN)\)\(K\) 指的是可能帶走的石頭數量,\(N\) 則是石頭總量。借鑒大佬的想法,添加一個數組(假設為 area),用以保存從 \(i\) 出發可以選擇的石頭數量。然后判斷從 \(i\) 出發,由 numi + area[i] 范圍內是否存在可以帶走 j - i 個石頭(\(j \in (num, i + area[i]]\)
      更詳細的描述見:藍橋杯 試題 算法訓練 禮物 C++ 詳解

      爆內存的代碼如下(最多過了 5 個 case,最少也是過了倆)

      import java.util.Scanner;
      
      /**
       * @author HuaWang135608
       * @date 2023.03.14 12:28:36
       * @description [試題 算法訓練 禮物](http://lx.lanqiao.cn/problem.page?gpid=T2990)
       */
      
      public class A1003_Present {
      
      	public static void main(String[] args) {
      		try (Scanner sc = new Scanner(System.in)) {
      			// 數據輸入
      			int src_n = sc.nextInt();
      			long src_s = sc.nextLong();
      			int[] src = new int[src_n];
      			for (int i=0; i<src_n; ++i) {
      				src[i] = sc.nextInt();
      			}
      			
      			// 數據處理
      			long sum = 0;
      			int num = 0;
      			int i, j;
      			for (i=0; i<src_n; ++i) { // 從 i 出發,獲取可選的石頭范圍
      				while (sum<src_s && num<src_n) { // 獲取當前可選的重量
      					sum += src[num++];
      				}
      				if (sum > src_s) { // 超重,拋掉最后一個石頭
      					sum -= src[--num];
      				}
      				if (num < i) { // 此時可選的數量小于出發點
      					sum = 0; // 總重量置 0
      					src[i] = 0; // 從 i 出發不能帶走任何石頭
      					num = i + 1; // 置于下一個出發點
      				} else {
      					sum -= src[i]; // 拋掉當前石頭
      					src[i] = num - i;// 可選石頭的數量
      				}
      			}
      			
      			int res = 0;
      			for (i=0; i<src_n; ++i) {
      				for (j=src[i]; j>res; --j) { // 可選范圍比已知最大范圍要大
      					// 后 j 個石頭沒越界,且后 j 個石頭重量要小于等于 S
      					if (i+j<src_n && src[i + j]>=j) {
      						res = j;
      						break;
      					}
      				}
      			}
      			res <<= 1;
      			
      			// 結果輸出
      			System.out.println(res);
      		}
      	}
      }
      

      AC 解法

      然后又是一番搜索,發現有老哥說 Scanner 性能太拉,又是一番 Ctrl C V,修正如下:
      此處參考:

      1. 藍橋杯算法訓練 禮物 java (不使用二分查找)
        這個佬好像用的新解法,沒仔細看。
      2. 為什么內存超限了,求高手解答(附代碼)
        image
      import java.io.BufferedReader;
      import java.io.IOException;
      import java.io.InputStreamReader;
      //import java.util.Scanner;
      
      /**
       * @author HuaWang135608
       * @date 2023.03.14 12:28:36
       * @description [試題 算法訓練 禮物](http://lx.lanqiao.cn/problem.page?gpid=T2990)
       */
      
      public class A1003_Present {
      	
      	private static int[] src;
      	private static int src_n;
      	private static long src_s;
      
      	public static void main(String[] args) throws IOException {
      		// 數據輸入
      //		try (Scanner sc = new Scanner(System.in)) {
      //			src_n = sc.nextInt();
      //			src_s = sc.nextLong();
      //			src = new int[src_n];
      //			for (int i = 0; i < src_n; ++i) {
      //				src[i] = sc.nextInt();
      //			}
      //		}
      		
      		try (InputStreamReader isr = new InputStreamReader(System.in)) {
      			try (BufferedReader br = new BufferedReader(isr)) {
      				String[] tmp = br.readLine().split(" ");
      				src_n = Integer.parseInt(tmp[0]);
      				src_s = Long.parseLong(tmp[1]);
      				
      				src = new int[src_n];
      				tmp = br.readLine().split(" ");
      				for (int i=0; i<src_n; ++i) {
      					src[i] = Integer.parseInt(tmp[i]);
      				}
      			}
      		}
      		
      		// 數據處理
      		// 結果輸出
      		System.out.println(solve1());
      	}
      
      	/**
      	 * 解法 1:暴力解法(超時,只能過 2 個 case)
      	 * 	從頭遍歷到尾部,每次檢驗可以帶走的石頭數量,可帶走更多則更新
      	 * @return 可以帶走的最大石頭數量
      	 */
      	public static int solve() {
      		int num = 0;
      		for (int i = 0; i + num < src.length; ++i) {
      			long s = src_s;
      			int n = 0;
      			// 從當前石頭出發,最多可以帶走多少石頭(結果為 n 個)
      			// j + n < length
      			// 代表若從當前出發,帶走 n 個 石頭后,若剩余不足 n 個石頭則不用繼續增加
      			for (int j = i; j + n < src.length; ++j) {
      				s -= src[j];
      				if (s >= 0) {
      					++n;
      				} else {
      					break;
      				}
      			}
      			// 判斷后 n 個石頭的重量
      			s = 0;
      			int rear = i + (n << 1);
      			for (int j = i + n; j < rear; ++j) {
      				s += src[j];
      			}
      			// 若后 n 個石頭重量大于可以攜帶的重量
      			while (s > src_s) {
      				s = s + src[i + (--n)]; // 前移曾加 1 個
      				s -= src[--rear] + src[--rear]; // 前移丟掉 2 個
      			}
      			if (rear - i > num) { // 若當前可攜帶量大于已有的最優結果,則更新
      				num = rear - i;
      			}
      		}
      		return num;
      	}
      
      	/**
      	 * 解法 2:空間換時間
      	 *  解法 1 中有大量重復的計算,使用一個表示可選區域大小的數組降低計算量
      	 * 參考:https://blog.csdn.net/Lyz_ID/article/details/122906021
      	 * @return 可以帶走的最大石頭數量
      	 */
      	public static int solve1() {
      		int i, j;
      		int num = 0;
      		long sum = 0;
      		
      		for (i=0; i<src_n; ++i) { // 從 i 出發,獲取可選的石頭范圍
      			while (sum<src_s && num<src_n) { // 獲取當前可選的重量
      				sum += src[num++];
      			}
      			if (sum > src_s) { // 超重,拋掉最后一個石頭
      				sum -= src[--num];
      			}
      			if (num < i) { // 此時可選的數量小于出發點
      				sum = 0; // 總重量置 0
      				src[i] = 0; // 從 i 出發不能帶走任何石頭
      				num = i + 1; // 置于下一個出發點
      			} else {
      				sum -= src[i]; // 拋掉當前石頭
      				src[i] = num - i;// 可選石頭的數量
      			}
      		}
      
      		num = 0;
      		for (i=0; i<src_n; ++i) {
      			for (j=src[i]; j>num; --j) { // 可選范圍比已知最大范圍要大
      				// 后 j 個石頭沒越界,且后 j 個石頭重量要小于等于 S
      				if (i+j<src_n && src[i+j]>=j) {
      					num = j;
      					break;
      				}
      			}
      		}
      		return (num << 1);
      	}
      
      }
      

      AC 貼圖:
      image

      時間復雜度約為 \(O(n)\)
      總結:Java 基礎太差,還是要好好學 Java。
      再次感謝各位佬的無私分享~

      posted @ 2023-03-14 17:26  華王135608  閱讀(125)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 在线视频中文字幕二区| 欧美一区二区三区欧美日韩亚洲| 日韩人妻无码精品久久| 青青在线视频一区二区三区| 福利一区二区在线播放| 久久毛片少妇高潮| 少妇宾馆粉嫩10p| 国产精品视频一区二区亚瑟| 久草热在线视频免费播放| 韩国无码av片在线观看| 久国产精品韩国三级视频| 凤台县| 亚洲中文字幕综合小综合| 中文人妻av高清一区二区| 国产精品福利午夜久久香蕉| 午夜福利偷拍国语对白| 国产极品粉嫩尤物一线天| 99久久国产综合精品女图图等你 | 国产69精品久久久久人妻刘玥| 2021av在线| 亚洲午夜福利精品无码不卡| √天堂资源地址在线官网| 精品偷自拍另类精品在线| 欧洲中文字幕一区二区| 久久综合九色综合97婷婷| 国产日韩av二区三区| 亚洲香蕉伊综合在人在线| 日韩免费美熟女中文av| 日本少妇自慰免费完整版| 国产中文字幕在线一区| 色哟哟www网站入口成人学校| 日韩国产成人精品视频| 久久精品国产精品第一区| 18成人片黄网站www| 久久国产精品色av免费看| 真人无码作爱免费视频| 国产成人午夜福利院| 亚洲欧洲日韩国内高清| 九色国产精品一区二区久久| 欧美大胆老熟妇乱子伦视频| 国产高清在线精品一区二区三区|