[背包变形] P1858 多人背包

探讨了01背包问题的前k优解求解方法,通过增加维度表示第k优解,利用单调序列特性,结合背包问题基本原理,实现了在限定条件下找到所有背包配置的总价值最大值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链接https://www.luogu.com.cn/problem/P1858.

题目描述

求01背包前k优解的价值和

DD 和好朋友们要去爬山啦!

他们一共有 K 个人,每个人都会背一个包。这些包 的容量是相同的,都是 V。可以装进背包里的一共有 N 种物品,每种物品都有 给定的体积和价值。

在 DD 看来,合理的背包安排方案是这样的: 每个人背包里装的物品的总体积恰等于包的容量。 每个包里的每种物品最多只有一件,但两个不同的包中可以存在相同的物品。

任意两个人,他们包里的物品清单不能完全相同。 在满足以上要求的前提下,所有包里的所有物品的总价值最大是多少呢?

输入格式

第一行三个数K、V、N

接下来每行两个数,表示体积和价值

输出格式

前k优解的价值和

输入 #1

2 10 5
3 12
7 20
2 4
5 6
1 1

输出 #1

57

说明/提示

对于100%的数据,K≤50,V≤5000,N≤200

过程

看到这题一脸懵 然后看题解 发现了背包9讲然后又去研究 发现有点高深 又去百度 找到了几篇较为通俗易懂的讲解背包的博客 然后算是稍微入了入门

这题是第k优解的背包问题 算是背包的变形 首先这题需要了解01背包的原理 已经01背包的一维表达 即:f[i]=max(f[i],f[i-w[i]+v[i]);
通过01背包的基本知识 我们知道*f[i]的决定因素只有f[i]f[i-w[i]+v[i]*所以增加一维k代表第k优解 那么f[i][k]是在i容量下的第k优解的值 那么f[i][1]->f[i][k]是呈单调的序列且f[i][1]是最优解

此时我们设变量a1,a2来分别表示第a1优解和第a2优解
a1指代f[i],a2指代f[i-w[i]+v[i]时 然后引用背包九讲中的一句话:一个正确的状态转移方程的求解过程遍历了所有可用的策略,也就覆盖了问题的所有方案 所以在这个过程中 较大的存入一个数组中保存 并使该k+1 因为在之前的状态中每次保存是最优的前n个(背包基础知识) 所以在后面的检测中 按照背包的一个物品一个物品选择 会不断更新最好的结果 也就可以获得前k(指人数的k)最优解 相加即为最有解

注意!!!
背包问题初始值选择 参考背包9讲或者直接搜索

代码

#include<bits/stdc++.h>
using namespace std;

int v,k,n,T=0;
int f[5005][55],w[205],c[205],t[55];

int main(){
	cin>>k>>v>>n;
	for(int i=1;i<=n;i++)
		cin>>w[i]>>c[i];
	for(int i=0;i<=5000;i++){
		for(int j=0;j<=50;j++){
			f[i][j]=-1999999;
		}
	}
	f[0][1]=0;
	for(int i=1;i<=n;i++){
		for(int j=v;j>=w[i];j--){
			int a1=1,a2=1,total=0;
			while(total<=k){
				if(f[j][a1]>f[j-w[i]][a2]+c[i])
					t[++total]=f[j][a1++];
				else
					t[++total]=f[j-w[i]][a2++]+c[i];
			}
			for(int x=1;x<=k;x++)
				f[j][x]=t[x];
		}
	}
	for(int i=1;i<=k;i++)
		T+=f[v][i];
	cout<<T;
	return 0;	
}
<think>嗯,用户问的是为什么玩家头顶的血条HUD用3D而不是UGUI,以及怎么用3D实现。首先,我需要回忆一下UGUI和3D HUD的区别。UGUI通常是基于屏幕空间的UI,适合固定在屏幕上的元素,比如玩家的血量、技能栏这些。而3D的HUD则是放在游戏世界中的,跟随物体移动,比如敌血条或者NPC的名字。 那为什么选择3D的呢?可能的原因有几个:首先,当物体在移动或者摄像机角度变化时,3D血条能更好地跟随物体,保持相对位置,而UGUI可能需要复杂的计算来转换坐标。其次,如果有个玩家或敌,每个都有自己的血条,3D的方式更容易管理,每个实例独立。另外,性能方面,如果有很动态物体,UGUI可能需要更的画布重建,而3D可能更高效,特别是用Shader处理的时候。 接下来是怎么实现的问题。在Unity里,通常有两种方法:使用3D文本或Sprite,或者用Shader。第一种方法可能是在3D物体上添加一个Canvas,设置为World Space,然后调整位置。不过要注意摄像机面对的问题,可能需要用Billboard脚本让血条始终面向摄像机。第二种方法是用Shader,比如创建Quad面片,用Shader绘制血条,这样性能更好,但需要一定的Shader知识。 用户可能的实际需求是做一个游戏中的角色血条,或者敌血条,需要血条跟随角色移动,并且在不同角度下都能正确显示。可能他们之前尝试过UGUI,但遇到了位置不准确或者性能问题。需要解释清楚两种方法的优缺点,以及具体步骤,可能还需要提到性能优化的部分,比如对象池或者GPU Instancing。 另外,用户可能对UGUI和3D UI的区别不是很清楚,所以需要解释两者的适用场景。比如,UGUI适合静态的、屏幕空间的元素,而3D UI适合动态的、世界空间的元素。同时,实现3D血条时要注意渲染顺序,避免被场景中的物体遮挡,可能需要调整Layer或者Shader的渲染设置。 可能还需要提到一些常见问题,比如血条的位置偏移,如何根据角色的高度调整血条的位置,或者在网络游戏中如何同步血条的状态。另外,性能方面,如果大量使用3D血条,合批处理或者使用更高效的渲染方式会更好。 最后,总结的时候要强调根据具体需求选择合适的方法,如果血条需要精确跟随物体并且有复杂的3D效果,就用3D HUD;如果是简单的静态显示,UGUI可能更合适。同时,给出实现的步骤,帮助用户快速上手。</think>在游戏开发中,玩家头顶的 **3D 血条 HUD**(Head-Up Display)通常用于与游戏世界中的物体(如角色、敌或可交互对象)保持空间同步,而 **UGUI**(Unity的UI系统)更适合屏幕固定的界面。以下是两者的区别及实现方法: --- ### **一、为什么选择 3D HUD 而非 UGUI?** 1. **空间一致性** - **3D HUD**:附着在游戏对象的 3D 空间中,会随物体移动、旋转或摄像机视角变化自动调整位置和透视,确保血条始终“长”在物体头顶。 - **UGUI**:基于屏幕坐标系(Screen Space),需要手动计算物体在屏幕上的位置,可能因物体移动或摄像机抖动导致血条漂移。 2. **性能优化** - **3D HUD**:通过 GPU 渲染(如 Shader 或 Sprite),适合大量动态对象(如大量敌血条)。 - **UGUI**:频繁更新屏幕坐标会导致 Canvas 重建,可能引发性能问题(尤其在移动端)。 3. **视觉效果** - **3D HUD**:支持透视变形、遮挡效果(如被墙壁遮挡时隐藏血条),更贴近 3D 世界的真实感。 - **UGUI**:始终显示在屏幕最上层,无法与场景物体自然交互。 --- ### **二、如何实现 3D 血条 HUD?** #### **方法 1:使用 Unity 的 World Space Canvas** 1. **创建 Canvas** - 新建 `Canvas`,设置 `Render Mode` 为 **World Space**。 - 调整 `RectTransform` 的尺寸和位置,使其附着在目标物体(如玩家头部)。 2. **绑定到游戏对象** - 将 Canvas 设为目标物体的子对象,或通过脚本动态更新位置: ```csharp public Transform target; // 目标物体(如玩家头部) public Vector3 offset; // 血条位置偏移(如头顶上方) void Update() { transform.position = target.position + offset; } ``` 3. **添加 Billboard 效果** - 让血条始终面向摄像机: ```csharp void Update() { transform.LookAt(Camera.main.transform); transform.Rotate(0, 180, 0); // 可选:调整朝向 } ``` #### **方法 2:Shader + 3D 面片(高性能方案)** 1. **创建 Quad 面片** - 在角色头顶添加一个 `Quad` 作为血条的载体。 2. **编写自定义 Shader** - 使用 Shader 绘制血条,例如通过 `UV` 坐标控制血条长度: ```glsl // 片段着色器示例 fixed4 frag (v2f i) : SV_Target { float healthRatio = _Health / _MaxHealth; if (i.uv.x > healthRatio) discard; // 裁剪超出生命值的部分 return _Color; } ``` 3. **动态更新血条** - 通过脚本修改 Shader 参数: ```csharp material.SetFloat("_Health", currentHealth); ``` --- ### **三、UGUI 的适用场景** - **静态界面**:如暂停菜单、背包系统。 - **屏幕固定元素**:如玩家自己的血量条(固定在屏幕角落)。 - **无需透视交互的简单需求**:如 2D 游戏中的血条。 --- ### **总结** - **3D HUD** 适合需要与游戏世界动态同步的 UI(如头顶血条、敌标记)。 - **UGUI** 适合静态或屏幕固定的界面元素。 - 实现 3D 血条的核心是 **World Space Canvas** 或 **Shader + 3D 几何体**,需根据项目需求选择性能和效果的平衡。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值