给定一组石头,每个石头有一个正数的重量。每一轮开始的时候,选择两个石头一起碰撞,假定两个石头的重量为x,y,x<=y,碰撞结果为
1. 如果x==y,碰撞结果为两个石头消失
2. 如果x != y,碰撞结果两个石头消失,生成一个新的石头,新石头重量为y-x
最终最多剩下一个石头为结束。求解最小的剩余石头质量的可能性是多少。
第一行输入石头个数(<=100)
第二行输入石头质量,以空格分割,石头质量总和<=10000
最终的石头质量
6 2 7 4 1 8 1
1
import java.util.*; public class Main{ public static void main(String[] args){ Scanner scanner=new Scanner(System.in); int n=scanner.nextInt(),sum=0,result=0; int[] nums=new int[n+1]; for(int i=1;i<=n;i++) { nums[i]=scanner.nextInt(); sum+=nums[i]; } boolean[] dp=new boolean[sum/2+1]; dp[0]=true; for(int i=1;i<=n;i++) for(int j=sum/2;j>=nums[i];j--) dp[j]|=dp[j-nums[i]]; for(int j=sum/2;j>=0;j--) if(dp[j]) { result=Math.abs(j-(sum-j)); break; } System.out.println(result); } }
#include <iostream> (720)#include <vector> #include <algorithm> using namespace std; class Solution { public: int test(int n, vector<int> weights) { int sum = 0; for (int weight:weights) { sum+=weight; } int maxCapcity = sum/2; vector<int> dp(maxCapcity+1,0); for (int i=0;i<n;i++) { for (int j=maxCapcity;j>=weights[i];j--) { dp[j] = max(dp[j],dp[j-weights[i]]+weights[i]); } } return sum - 2*dp[maxCapcity]; } }; int main() { int n; cin >> n; vector<int> weights(n); for (int i=0;i<n;i++) { cin >> weights[i]; } int res = Solution().test(n,weights); cout << res; return 0; }
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int rockNum = Integer.parseInt(sc.nextLine()); int[] rockWeights = new int[rockNum]; String[] strs = sc.nextLine().split(" "); int sumWeight = 0; for (int i = 0; i < rockNum; i++) { rockWeights[i] = Integer.parseInt(strs[i]); sumWeight += rockWeights[i]; } int[] dp = new int[(sumWeight / 2) + 1]; for (int rockWeight : rockWeights) { for (int i = sumWeight / 2; i >= rockWeight; i--) { dp[i] = Math.max(dp[i], dp[i - rockWeight] + rockWeight); } } System.out.println(sumWeight - 2 * dp[sumWeight / 2]); } }
#include<iostream> #include<algorithm> #include<cmath> using namespace std; int main(){ int num; cin >> num; int *storn = new int[num]; for(int i = 0; i < num; i++) cin >> storn[i]; int sum = 0; for(int i = 0; i < num; i++) sum += storn[i]; int max_weight = sum / 2; int *weight = new int[max_weight + 1]; for(int i = 0; i < num; i++){ for(int j = max_weight; j >= storn[i]; j--){ weight[j] = max(weight[j], weight[j - storn[i]] + storn[i]); } } cout << sum - 2 * weight[max_weight]; return 0; }
package 快手2020校园招聘秋招笔试工程C试卷; import java.util.Scanner; /** * Project: 100% * Author : en_zhao * Email : * Date : 2020/8/3 */ public class Main002 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); //每个物品的重量 int num[] = new int[n+1]; int s = 0; //求总数 for(int i = 0;i < n;i++){ num[i] = sc.nextInt(); s += num[i]; } //背包的重量 int W = s / 2; //背包最优解 java默认初始化为0 int[] dp = new int[W + 1]; for(int i = 0; i < n;i++){ for(int j = W; j-num[i] >= 0 ;j--){ dp[j] = Math.max(dp[j], dp[j-num[i]]+num[i]); } } System.out.println(s - dp[W] - dp[W]); } }
package main import ( "fmt" ) func main() { var n, tmp, sum, max int var w []int fmt.Scan(&n) for i := 0; i < n; i++ { fmt.Scan(&tmp) sum += tmp w = append(w, tmp) } flag := make([]bool, sum/2+1) flag[0] = true for _, v := range w { for i := sum / 2; i >= v; i-- { flag[i] = flag[i] || flag[i-v] } } for i := sum / 2; i >= 0; i-- { if flag[i] { fmt.Print(sum - 2*i) break } } }
我开始维护CSDN了,来点个赞呗~
import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int[] nums = new int[n]; int sum = 0; for (int i = 0; i < n; i++) { nums[i] = scanner.nextInt(); sum += nums[i]; } int[][] dp = new int[n + 1][sum / 2 + 1]; for (int i = 1; i <= n; i++) { for (int j = 0; j <= sum / 2; j++) { if (j >= nums[i - 1]) { dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - nums[i - 1]] + nums[i - 1]); } else { dp[i][j] = dp[i - 1][j]; } } } System.out.print(sum - 2 * dp[n][sum / 2]); } }
import java.util.*; /** * @Author: * @Date: 2020/7/26 19:48 * <p> * 功能描述: */ public class Main { public static void main(String[] args){ Scanner sc = new Scanner(System.in); int n = sc.nextInt(); sc.nextLine(); int[] stones = new int[n] ; for(int i = 0; i < n;i++){ stones[i] = sc.nextInt(); } int ans = lastStoneWeightII(stones); System.out.println(ans); } public static int lastStoneWeightII(int[] stones) { /* 1.换一种想法,就是将这些数字分成两拨,使得他们的和的差最小 2.因此可以简单地把所有石头看作两堆,假设总重量为 sum, 则问题转化为背包问题:如何使两堆石头总重量接近 sum / 2 3.两堆石头的价值(重量)都只能接近 */ int len = stones.length; /* 获取石头总重量 */ int totalStone = 0; for (int i : stones) { totalStone += i; } int maxCapacity = totalStone / 2; /* 1.这个是0-1背包的dp定义,dp[i][w]: 前i个商品,当容量为w时,最大价值为dp[i][w] 2.对照一下此题dp数组定义,dp[i][j]: 前i个石头,当容量为j时,最大重量为dp[i][j] */ int[][] dp = new int[len + 1][totalStone + 1]; for (int i = 1; i < len + 1; i++) { for (int j = 1; j < maxCapacity + 1; j++) { if (j - stones[i - 1] < 0) { dp[i][j] = dp[i - 1][j]; } else { dp[i][j] = Math.max(dp[i - 1][j - stones[i - 1]] + stones[i - 1], dp[i - 1][j]); } } } return totalStone - 2 * dp[len][maxCapacity]; } }
//0-1背包,昨天有一个类似的三层背包 和这个非常类似 都快给我搞混了,其实挺好理解的 //菜菜 #include<vector> using namespace std; class Solution{ public: int getMin(vector<int> arr){ int sum = 0; for(int i=0;i<arr.size();i++){ sum +=arr[i]; } int C = sum/2; vector<vector<int>> dp(arr.size(),vector<int>(C+1,0)); for(int j=0;j<=C;j++){ dp[0][j] = arr[0] <=j?arr[0]:0; } for(int i=1;i<arr.size();i++){ for(int j=0;j<=C;j++){ dp[i][j] = dp[i-1][j]; if(arr[i] <= j){ dp[i][j] = max(dp[i][j],arr[i] + dp[i-1][j-arr[i]]); } } } return sum - dp[arr.size()-1][C] * 2; } }; int main(){ int n; cin>>n; vector<int> arr(n); for(int i=0;i<n;i++){ cin>>arr[i]; } Solution c1; cout<<c1.getMin(arr)<<endl; return 0; }
//dp求法 #include<iostream> #include<vector> #include<algorithm> using namespace std; int main() { int n = 0 ; cin>>n; vector<int>nums; int tmp = 0; int sum = 0; while(cin>>tmp) { nums.push_back(tmp); sum+=tmp; } //dp int C = sum/2; vector<vector<int>>dp(n,vector<int>(C+1,0)); for(int c = 0; c<=C ; ++c) dp[0][c] = nums[0]>c?0:nums[0]; for(int i = 1 ; i < n ; ++i) for(int c = 0 ; c <=C ; ++c) { if(c>=nums[i]) dp[i][c] = max(dp[i-1][c] , nums[i] + dp[i-1][c-nums[i]]); else dp[i][c] = dp[i-1][c]; } cout<<sum - dp[n-1][C] * 2; return 0; }
#include<iostream> (720)#include<vector> #include<cassert> (4983)#include<algorithm> using namespace std; class Solution{ private: //物品价值列表v, 重量列表w,当前背包容量c , 当前考虑的物品索引范围[0,index],返回此时能获得的最大价值 vector<vector<int>>meno; int maxValue_recursion(const vector<int>&v, const vector<int>&w, int c, int index) { //终止条件 if (c == 0 || index < 0)return 0; //递归过程 if (meno[index][c] != -1)return meno[index][c]; int res = maxValue_recursion(v, w, c, index - 1); if (c >= w[index]) res = max(res, v[index]+maxValue_recursion(v, w, c - w[index], index - 1)); meno[index][c] = res; return res; } public: int maxValue(const vector<int>& v, const vector<int>& w, int C) { assert(v.size() == w.size()); int n = v.size(); meno = vector<vector<int>>(n,vector<int>(C+1,-1)); return maxValue_recursion(v, w, C, n - 1); } }; int main() { int n = 0; cin>>n; vector<int>v; int tmp = 0; int sum = 0; while(cin>>tmp) { v.push_back(tmp); sum+=tmp; } Solution sl; int res = sum - sl.maxValue(v,v,sum/2)*2; cout<<res;
#include<iostream> using namespace std; const int N = 110; const int M = 10010; int a[N]; int f[N][M]; int main() { int n; scanf("%d", &n); int sum = 0; for (int i = 1; i <= n; i ++ ) { scanf("%d", &a[i]); sum += a[i]; } int V = sum / 2; for (int i = 1; i <= n; i ++ ) { for (int j = 0; j <= V; j ++ ) { f[i][j] = f[i - 1][j]; if (j >= a[i]) f[i][j] = max(f[i][j], f[i - 1][j - a[i]] + a[i]); } } cout << (sum - f[n][V]) - f[n][V]; return 0; }