TZOJ.6865.轮渡车辆

Posted 须藤要

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TZOJ.6865.轮渡车辆相关的知识,希望对你有一定的参考价值。

这道题有很多解法,这里介绍的是01背包思想

描述

一条船正准备装载车辆过河,船上有一左一右两个车道(长度均为L)可以停车,所有的车辆排成一个队伍准备从前往后逐辆上船(即前面没上,则后面不能上船,上船后车子沿车道正向停放),请问最多能上几辆车。

输入

第一行为整数L(单位:米),表示车道的长度。接下来若干行为车队,每行有一个整数,表示车子的长度(单位:厘米)。最后一行为0,表示输入结束。车道和车长都不超过100米。

输出

输出最多能上的车子数量。.

样例输入

50
2500
3000
1000
1000
1500
700
800
0

样例输出

6

题解

  • 题目所说车道和车长都不超过100米。所以我们可以考虑应用背包思想
  • 因为船有两个车道,而且前面只要有一辆车不能上去的话,这辆车后面所有的车都不能上去,所以当我们读入到前面所有车辆的总长度大于两个车道的长度或有一辆车的长度单独大于单独一个车道的时候就可以停止输入(因为后面的车都不能上船)。
  • 可以转换成有n个物品放入两个背包中(所有物品必须全部放入),在n个物品中选择k个物品的体积尽量大放入第一个背包中,其余的放入第二个背包中。因此我们可以用01背包来选择物品,使第一个背包尽量装满。同时我们也要保证剩余的物品也能放入第二个背包中,所以我们用总长度减去背包大小为L所装的最大物品后就是第二个背包所装的物品,sum - f [ L ] < = L 。
    在这里插入图片描述
  • 当f [ i ] [ j ]更新后说明放入了第一个背包,否则将放入第二个背包,因此放入车辆的个数加1;
  • 因为我们默认前i个物品都是能装下的,当出现了两个背包都不能装下物品的时候,再来一个物品也必定不能装下,因此放入的车辆的个数就不会更新。

AC代码

#include<cstdio>
#include<algorithm>
using namespace std;
int f[10003];
int ans,s;
int main(){
	int L,a;
	scanf("%d",&L);L*=100;//车的长度是m,把车道转换成cm
	while(scanf("%d",&a),a)
	{
		ans+=a;//记录车的总长度
		if(ans>2*L||a>L)break;
		for(int j=L;j>=a;j--)//01背包
		{
			f[j]=max(f[j],f[j-a]+a);
		}
		if(ans-f[L]<=L)s++;//代表两个背包都能装下
		else break;
	}
	if(a)while(scanf("%d",&a),a);//把剩下的数读入完
	printf("%d",s);
	return 0;
}

以上是关于TZOJ.6865.轮渡车辆的主要内容,如果未能解决你的问题,请参考以下文章

TZOJ.6865.轮渡车辆

TZOJ.6865.轮渡车辆

应用移动端车牌识别技术,避免汽车轮渡中的逃票漏票行为

如何使 Flutter graphql 订阅与轮渡包一起使用?

在 ListView 上生成 OnClickEvent 而不实际单击项目

如何在Android的谷歌地图片段中更改默认的蓝色圆形位置图标?