首页 > 其他分享 >动态规划 Part II

动态规划 Part II

时间:2023-07-01 18:33:55浏览次数:31  
标签:... 破损 int sum II Part 砝码 Limit 动态

大家好,我是wangmy。

众所周知动态规划将原问题分解成若干个子问题,再把子问题分解成若干更多子问题。先求解子问题,再从这些子问题的解得到原问题的解。

今天我给大家分享一下动态规划的几道题和参考代码。

砝码秤重

题目描述(Description)

设有n种砝码,第k种砝码有Ck个,每个重量均为Wk,求:用这些砝码能秤出的不同重量的个数,但不包括一个砝码也不用的情况。

动态规划 Part II_i++


输入格式(Format Input)

输入的第一行只有一个数n,表示不同的砝码的种类数. 第2行至第n+1行,每行有两个整数.第k+1行的两个数分别表示第k种砝码的个数和重量.

输出格式(Format Output)

输出中只有一行数据:Total=N。表示用这些砝码能秤出的不同重量数。

输入样例(Sample Input)

2 
2 2
2 3

输出样例(Sample Output)

Total=8

限制(Restrictions)

时间限制(Time Limit):  1000 ms
内存限制(Memory Limit):  65536 KB

说明/提示(Hint)

对于100%的数据,砝码的种类n满足:1≤n≤100;
对于30%的数据,砝码的总数量C满足:1≤C≤20;
对于100%的数据,砝码的总数量C满足:1≤C≤100;
对于所有的数据,砝码的总重量W满足:1≤W≤400000;

参考代码

#include<bits/stdc++.h>
using namespace std;
int n, a[110], cnt, sum;
bool f[400010];
int main()
{
	cin >> n;
	int c, w;
	for(int i = 1; i <= n; i++){
		scanf("%d%d", &c, &w);
		sum += c * w;
		//二进制打包,极大减少打包次数 
		for(int j = 1; c >= j; j <<= 1) {
			a[++cnt] = j * w;
			c -= j;
		}
		if(c) a[++cnt] = c * w;
	}
	f[0] = 1;
	for(int i = 1; i <= cnt; i++){
		//从大到小枚举,保证大状态依赖的小状态未被更新(上一维) 
		for(int j = sum; j >= a[i]; j--)
			if(f[j - a[i]]) f[j] = 1;
	}
	int ans = 0;
	for(int i = 1; i <= sum; i++) if(f[i]) ans++;
	printf("Total=%d", ans);
	return 0;
}



石子归并

题目描述(Description)

有一堆石头质量分别为W1,W2,…,Wn.(Wi≤10000),将石头合并为两堆,使两堆质量的差最小。


输入格式(Format Input)

输入第一行只有一个整数n(1≤n≤50),表示有n堆石子。接下去的n行,为每堆石子质量。

输出格式(Format Output)

输出只有一行,该行只有一个整数,表示最小的质量差.

输入样例(Sample Input)

5 
5
8
13
27
14

输出样例(Sample Output)

3

限制(Restrictions)

时间限制(Time Limit):  1000 ms
内存限制(Memory Limit):  65536 KB

参考代码

#include<bits/stdc++.h>
using namespace std;
bool f[55][500010];
int n,a[55],sum;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		sum+=a[i];
	}
	f[0][0]=1;
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<=sum;j++)
		{
			f[i][j]=f[i-1][j];
			if(j>=a[i]&&f[i-1][j-a[i]])
			{
				f[i][j]=1;
			}
		}
	}
	for(int i=sum/2;i>=0;i--)
	{
		if(f[n][i])
		{
			printf("%d",sum-i-i);
			return 0;
		}
	}
	return 0;
}


补圣衣

题目描述(Description)

有四个人,每人身上的衣服分别有s1,s2,s3和s4处破损,而且每处破损程度不同,破损程度用需修好它用的时间表示(A1...As1,B1...Bs2,C1...Cs3,D1...Ds4)。不过你可以同时修补2处破损。但是这2处破损,只能是同一件衣服上的。就是说你只能同时修补一件衣服,修好了,才能修补下一件。


输入格式(Format Input)

本题包含5行数据:
第1行,为s1,s2,s3,s4(1≤s1,s2,s3,s4≤20) 
第2行,为A1...As1 共s1个数,表示第一件衣服上每个破损修好它所需的时间 
第3行,为B1...Bs2 共s2个数,表示第二件衣服上每个破损修好它所需的时间
第4行,为C1...Cs3 共s3个数,表示第三件衣服上每个破损修好它所需的时间
第5行,为D1...Ds4 共s4个数,表示第四件衣服上每个破损修好它所需的时间 (1≤A1...As1,B1...Bs2,C1...Cs3,D1...Ds4≤60

输出格式(Format Output)

输出一行,为修好四件衣服所要的最短时间。

输入样例(Sample Input)

1 2 1 3		
5
4 3
6
2 4 3

输出样例(Sample Output)

20

限制(Restrictions)

时间限制(Time Limit):  1000 ms
内存限制(Memory Limit):  65536 KB

参考代码

#include<bits/stdc++.h>
using namespace std;
int s[5], a[25], sum, ans;
bool dp[1210];

int main()
{
	
	for(int i = 1; i <= 4; i++) scanf("%d", &s[i]);
	
	for(int t = 1; t <= 4; t++){
		
		sum = 0;
		memset(dp, 0, sizeof(dp));
		for(int i = 1; i <= s[t]; i++) scanf("%d", &a[i]), sum += a[i];
		
		dp[0] = 1;
		for(int i = 1; i <= s[t]; i++){
			for(int j = sum; j >= a[i]; j--)
				if(dp[j - a[i]]) dp[j] = 1;
		}
		int mid = sum / 2;
		
		for(int i = mid; i >= 0; i--){
			if(dp[i]){
				ans += sum - i;
				break;
			}
		} 
	}
	cout << ans;
	

	return 0;
}

今天的分享到此结束,我们下次再见。(希望大家有自己的思考,不要一味着抄代码)

标签:...,破损,int,sum,II,Part,砝码,Limit,动态
From: https://blog.51cto.com/wangmy666isking/6600692

相关文章

  • 结合静态与动态分析优势范围的fuzzer:Arbiter
    对于Arbier这款新型fuzzer的研究,目前网络上几乎没有内容,因此大部分内容的直接来源于Arbier的论文《Arbiter:BridgingtheStaticandDynamicDivideinVulnerabilityDiscoveryonBinaryPrograms》,该论文随着2022年8月的USENIX安全研讨会的论文集中发表。1.引言当前最先......
  • 算法学习day03链表part01-203、707、206
    packageSecondBrush.LinkedList.LL1;/***203.移除链表元素*删除链表中等于给定值val的所有节点。*自己再次概述一下这个过程:*1.移除元素,要采用设置虚拟节点的方式,因为那样不需要考虑头结点问题*2.设置两个虚拟指向*3.移除元素就是遍历链表,然后碰到目标值......
  • 算法学习day04链表part02-24、19、0207、142
    packageSecondBrush.LinkedList.LL1;/***24.两两交换链表中的节点**/publicclassSwapNodesInPairs_24{publicListNodeswapPairs(ListNodehead){ListNodedummyhead=newListNode(-1);dummyhead.next=head;ListNodecur......
  • 将onnx的静态batch改为动态batch及修改输入输出层的名称
    目录背景操作修改输入输出层修改输入输出层名称完整代码背景在模型的部署中,为了高效利用硬件算力,常常会需要将多个输入组成一个batch同时输入网络进行推理,这个batch的大小根据系统的负载或者摄像头的路数时刻在变化,因此网络的输入batch是在动态变化的。对于pytorch等框架来说,我......
  • LeetCode 142. 环形链表 II
    /***Definitionforsingly-linkedlist.*structListNode{*intval;*ListNode*next;*ListNode(intx):val(x),next(NULL){}*};*/classSolution{public:ListNode*detectCycle(ListNode*head){if(!head)return......
  • 动态树&Splay学习笔记
    前置芝士:SplayLCT(Link-CutTree)使用场景:动态树问题。基本概念:原树:给定的原始树。实边:在原树中节点\(cur\)选取一个子节点\(son\),则\(cur-son\)的连边为实边。虚边:不是实边。实链:由实边构成的链。基本思想:将原树中的一条链,用一颗平衡树(一般是Splay)来维护,其中......
  • 代码随想录算法训练营第二十一天| 216.组合总和III 17.电话号码的字母组合
    216.组合总和III  思路:很像上一个组合类型的题目,唯一不同的就是自己写一个sum代码:1voidconvertBST_cur(TreeNode*root,vector<TreeNode*>&nodes)2{3if(!root)return;4if(root->left)convertBST_cur(root->left,nodes);5nodes.push_bac......
  • 【任务分配】基于matlab实现多无人机动态任务分配附matlab代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 动态规划之二维费用的背包问题
    问题二维费用的背包问题是指:对于每件物品,具有两种不同的费用;选择这件物品必须同时付出这两种代价;对于每种代价都有一个可付出的最大值(背包容量)。问怎样选择物品可以得到最大的价值。设这两种代价分别为代价1和代价2,第i件物品所需的两种代价分别为a[i]和b[i]。两种代价可付出的最......
  • 动态规划之 附录二:背包问题的搜索解法
    《背包问题九讲》的本意是将背包问题作为动态规划问题中的一类进行讲解。但鉴于的确有一些背包问题只能用搜索来解,所以这里也对用搜索解背包问题做简单介绍。大部分以01背包为例,其它的应该可以触类旁通。简单的深搜对于01背包问题,简单的深搜的复杂度是O(2^N)。就是枚举出所有2^N......