2019年我能变强组队训练赛第二场 问题 K: PACKING (01背包+快读+o3优化)

题目描述
It was bound to happen. Modernisation has reached the North Pole. Faced with escalating costs for feeding Santa Claus and the reindeer, and serious difficulties with security, NP Management has decided to do away with the traditional sleigh and adopt delivery by drone (magic, superfast drone).
Lack of investment capital means that the new system will start small, and hopefully grow in the years to come. For the first test run in 2017 there will be only two drones and they will have limited carrying capacity. PR is, of course, all important. There will be disappointment, and NP Management has decided to focus on delivering only the most expensive toys to the richest children, so as to focus the worst of the disappointment on those who have the greatest experience of coping (the poor).
Choosing the presents to deliver is your problem. You are being asked to develop an algorithm to select the cargo to deliver, given weight limits for each of the drones and a list of candidate presents with weights and values. Your goal is to maximise the value of gifts delivered.

输入
Input will consist of a series of problems. The first line of the input holds a single integer P being the number of problems. Then for each problem there will be three lines of input. The first line holds three integers: N (1 <= N <= 100) being the number of candidate presents; W1 and W2 (1 <= W1, W2 <= 1000) being the weight limits of the two drones respectively. The second line holds N integers (1 <= wi <= 100) being the weights of each of the candidate presents and the third line holds N integers (1 <= vi <= 100) being the values of the presents (in thousand dollar units). All lines are formatted with single spaces between numbers and no leading or trailing spaces.

输出
For each problem your program should output one line with the text “Problem “ and the number of the problem (counting from 1) followed by a colon, a space and the total value of presents shipped by the drone pair.

样例输入
复制样例数据
2
4 9 4
3 4 5 6
5 7 9 10
6 9 11
3 4 5 6 3 4
2 3 4 5 3 3
样例输出
Problem 1: 22
Problem 2: 16

真是个神仙题。。服了,打的时候水过了,然后重判把所有过了的代码都hack掉了(这种操作我也是第一次见,tql)

思路:01背包变形,对于每个物品有不选,放进第一个背包,放进第二个背包,三种操作,那么最直观的写法就是三重循环,枚举物品个数,两个背包的容量,然后进行01背包。下面贴上初始代码(一直t的代码)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N =1005;
int dp[N][N];
int v[N],w[N];
int main()
{
	int t,cas=1;
	scanf("%d",&t);
	while(t--)
	{
		int n,m1,m2;
		scanf("%d%d%d",&n,&m1,&m2);
		for(int i=1;i<=n;i++)
			scanf("%d",&v[i]);
		for(int i=1;i<=n;i++)
			scanf("%d",&w[i]);
		memset(dp,0,sizeof dp);
		int lower,sum=0;
		for(int i=1;i<=n;i++)
		{
			for(int j=m1;j>=0;j--)
			{
				for(int k=m2;k>=0;k--)
				{
					if(j>=v[i]) 
						dp[j][k]=max(dp[j][k],dp[j-v[i]][k]+w[i]);
					if(k>=v[i])
						dp[j][k]=max(dp[j][k],dp[j][k-v[i]]+w[i]);
				}
			}
		}
		printf("Problem %d: %d\n",cas++,dp[m1][m2]);	
	}
	return 0;
 } 


上面这个代码是o(n * (m^2))的,n最大100,m最大1000,总时间复杂度是1e8左右,刚好被卡了一点,一般来说4e7左右是极限了。那么就想办法优化(自己没想到,怪我见的世面太少)
下面贴上借鉴了dks大佬思路的代码(貌似他是从学弟那来的思路hhh),用的是快读+o3优化+max三目运算符优化(这个不加也会t,我真服了,tql)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#pragma GCC optimize(3)
#define max(a,b) a>b?a:b
const int N =1005;
int dp[N][N];
int v[N],w[N];
template<class T>void read(T &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch<'0'||ch>'9')  {f|=(ch=='-');ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x=f?-x:x;
    return;
}
int main()
{
	int t,cas=1,n,m1,m2;
	read(t);
	while(t--)
	{
		read(n);read(m1);read(m2);
		for(int i=1;i<=n;i++)
			read(v[i]);
		for(int i=1;i<=n;i++)
			read(w[i]);
		for(int i=0;i<=m1;i++)
			for(int j=0;j<=m2;j++)
				dp[i][j]=0;
		for(int i=1;i<=n;i++)
		{
			for(int j=m1;j>=0;j--)
				for(int k=m2;k>=0;k--)
				{
					if(j>=v[i])
						dp[j][k]=max(dp[j][k],dp[j-v[i]][k]+w[i]);
					if(k>=v[i])
						dp[j][k]=max(dp[j][k],dp[j][k-v[i]]+w[i]);
				}
		}
		printf("Problem %d: %d\n",cas++,dp[m1][m2]);
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值