C# 卡车装车示例
Posted 多见多闻
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# 卡车装车示例相关的知识,希望对你有一定的参考价值。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TruckLoader : MonoBehaviour
// 货物信息结构体
public struct CargoInfo
public float length; // 长度
public float width; // 宽度
public float height; // 高度
public float weight; // 重量
public Vector3 position; // 位置
public Quaternion rotation; // 旋转方向
public CargoState state; // 状态
// 货物状态枚举类型
public enum CargoState
NotPlaced, // 未摆放
Placed, // 已摆放
CannotBePlaced // 无法摆放
// 数学模型算法枚举类型
public enum Algorithm
Greedy, // 贪心算法
Evolutionary // 进化算法
// 卡车最大载重和总体积限制
public float maxTotalWeight = 10000.0f;
public float maxTotalVolume = 100.0f;
// 当前使用的数学模型算法
private Algorithm currentAlgorithm = Algorithm.Greedy;
// 开始装车
public void StartLoadingTruck()
// 选择一个数学模型算法
currentAlgorithm = Algorithm.Greedy;
// 获取所有货物的信息
List<CargoInfo> cargoList = GetCargoList();
// 计算所有货物的重心
Vector3 centerOfMass = CalculateCenterOfMass(cargoList);
// 设置货物的起始位置和旋转方向
foreach (CargoInfo cargo in cargoList)
cargo.position = centerOfMass + new Vector3(0, cargo.height / 2.0f, 0);
cargo.rotation = Quaternion.identity;
cargo.state = CargoState.NotPlaced;
// 生成所有摆放方案
List<List<CargoInfo>> allLayouts = GenerateAllLayouts(cargoList);
// 找到符合要求的最优摆放方案
List<CargoInfo> bestLayout = FindBestLayout(allLayouts);
// 将货物摆放到卡车上
PlaceCargoToTruck(bestLayout);
// 生成所有货物的摆放方案
List<List<CargoInfo>> GenerateAllLayouts(List<CargoInfo> cargoList)
// 创建一个空的方案列表
List<List<CargoInfo>> allLayouts = new List<List<CargoInfo>>();
// 递归生成所有可能的摆放方案
GenerateAllLayouts(cargoList, new List<CargoInfo>(), allLayouts);
return allLayouts;
// 递归生成所有可能的摆放方案
void GenerateAllLayouts(List<CargoInfo> cargoList, List<CargoInfo> currentLayout, List<List<CargoInfo>> allLayouts)
// 判断是否已经完成了一个方案的生成
if (cargoList.Count == 0)
// 将当前方案添加到列表中
allLayouts.Add(new List<CargoInfo>(currentLayout));
return;
// 获取第一个货物
CargoInfo cargo = cargoList[0];
cargoList.RemoveAt(0);
// 尝试将货物摆放到当前方案中的所有位置和旋转方向
for (int i = 0; i < 4; i++)
cargo.rotation = Quaternion.Euler(0, i * 90, 0);
for (float x = 0; x <= transform.localScale.x - cargo.length; x += 0.1f)
for (float y = 0; y <= transform.localScale.y - cargo.height; y += 0.1f)
for (float z = 0; z <= transform.localScale.z - cargo.width; z += 0.1f)
cargo.position = new Vector3(x, y, z);
cargo.state = CargoState.Placed;
if (IsColliding(cargo, currentLayout))
cargo.state = CargoState.CannotBePlaced;
continue;
if (!IsWithinLimitations(cargo, currentLayout))
cargo.state = CargoState.CannotBePlaced;
continue;
// 将货物添加到当前方案中
currentLayout.Add(cargo);
// 递归生成下一个货物的摆放方案
GenerateAllLayouts(cargoList, currentLayout, allLayouts);
// 移除当前方案中的货物
RemoveCargoFromLayout(cargo, currentLayout);
// 将第一个货物重新加入到列表中
cargoList.Insert(0, cargo);
// 判断两个货物是否有碰撞
bool IsColliding(CargoInfo cargo1, List<CargoInfo> currentLayout)
foreach (CargoInfo cargo2 in currentLayout)
Bounds bounds1 = new Bounds(cargo1.position + new Vector3(cargo1.length / 2.0f, cargo1.height / 2.0f, cargo1.width / 2.0f),
new Vector3(cargo1.length, cargo1.height, cargo1.width));
Bounds bounds2 = new Bounds(cargo2.position + new Vector3(cargo2.length / 2.0f, cargo2.height / 2.0f, cargo2.width / 2.0f),
new Vector3(cargo2.length, cargo2.height, cargo2.width));
if (bounds1.Intersects(bounds2))
return true;
return false;
// 判断货物是否符合限制条件
bool IsWithinLimitations(CargoInfo cargo, List<CargoInfo> currentLayout)
float totalWeight = 0.0f;
float totalVolume = 0.0f;
foreach (CargoInfo otherCargo in currentLayout)
totalWeight += otherCargo.weight;
totalVolume += otherCargo.length * otherCargo.width * otherCargo.height;
if (totalWeight + cargo.weight > maxTotalWeight || totalVolume + cargo.length * cargo.width * cargo.height > maxTotalVolume)
return false;
return true;
// 移除当前方案中的货物
void RemoveCargoFromLayout(CargoInfo cargo, List<CargoInfo> currentLayout)
currentLayout.Remove(cargo);
cargo.state = CargoState.NotPlaced;
// 找到符合要求的最优摆放方案
List<CargoInfo> FindBestLayout(List<List<CargoInfo>> allLayouts)
switch (currentAlgorithm)
case Algorithm.Greedy:
default:
return FindBestGreedyLayout(allLayouts);
case Algorithm.Evolutionary:
// TODO: 实现进化算法查找最优摆放方案的功能
return new List<CargoInfo>();
// 使用贪心算法查找最优摆放方案
List<CargoInfo> FindBestGreedyLayout(List<List<CargoInfo>> allLayouts)
List<CargoInfo> bestLayout = null;
float bestScore = float.MinValue;
foreach (List<CargoInfo> layout in allLayouts)
// 计算货物的最大高度
float maxHeight = CalculateMaxHeight(layout);
// 计算摆放方案的得分
float score = CalculateScore(layout, maxHeight);
// 更新最优摆放方案
if (score > bestScore)
bestScore = score;
bestLayout = layout;
return bestLayout;
// 计算货物的最大高度
float CalculateMaxHeight(List<CargoInfo> cargoList)
float maxHeight = 0.0f;
foreach (CargoInfo cargo in cargoList)
float height = cargo.position.y + cargo.height / 2.0f;
if (height > maxHeight)
maxHeight = height;
return maxHeight;
// 计算摆放方案的得分
float CalculateScore(List<CargoInfo> cargoList, float maxHeight)
float totalWeight = 0.0f;
float totalVolume = 0.0f;
foreach (CargoInfo cargo in cargoList)
totalWeight += cargo.weight;
totalVolume += cargo.length * cargo.width * cargo.height;
// 根据总体积和最大高度计算得分
float score = totalVolume / maxHeight;
return score;
// 将货物摆放到卡车上
void PlaceCargoToTruck(List<CargoInfo> cargoList)
foreach (CargoInfo cargo in cargoList)
if (cargo.state != CargoState.Placed)
continue;
GameObject cargoObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
cargoObject.transform.localScale = new Vector3(cargo.length, cargo.height, cargo.width);
cargoObject.transform.position = cargo.position;
cargoObject.transform.rotation = cargo.rotation;
// TODO: 添加更多的货物信息,例如颜色、纹理等
cargoObject.transform.parent = transform;
// 获取所有货物的信息
List<CargoInfo> GetCargoList()
List<CargoInfo> cargoList = new List<CargoInfo>();
// TODO: 获取货物列表并设置货物的长、宽、高、重量等参数
return cargoList;
// 计算所有货物的重心
Vector3 CalculateCenterOfMass(List<CargoInfo> cargoList)
Vector3 centerOfMass = Vector3.zero;
float totalWeight = 0.0f;
foreach (CargoInfo cargo in cargoList)
centerOfMass += cargo.weight * (cargo.position + new Vector3(0, cargo.height / 2.0f, 0));
totalWeight += cargo.weight;
centerOfMass /= totalWeight;
return centerOfMass;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TruckLoader : MonoBehaviour
// 货物信息参数
public float cargoLength;
public float cargoWidth;
public float cargoHeight;
public float cargoWeight;
// 限制规则参数
public float maxTotalWeight;
public float maxTotalVolume;
// 数学模型算法选择
public enum AlgorithmType
BruteForce,
GreedyAlgorithm,
DynamicProgramming,
GeneticAlgorithm
public AlgorithmType algorithmType;
// 摆放方案导出
public void ExportLayout()
// TODO: 实现导出摆放方案的功能
// 货物摆放到卡车上
public void LoadCargoToTruck()
// 根据用户选择的算法类型,选择相应的算法进行货物摆放
switch (algorithmType)
case AlgorithmType.BruteForce:
BruteForceAlgorithm();
break;
case AlgorithmType.GreedyAlgorithm:
GreedyAlgorithm();
break;
case AlgorithmType.DynamicProgramming:
DynamicProgrammingAlgorithm();
break;
case AlgorithmType.GeneticAlgorithm:
GeneticAlgorithm();
break;
default:
break;
// 枚举类型,表示货物的状态
enum CargoState
NotPlaced, // 没有摆放
Placed, // 已经摆放
CannotBePlaced // 无法摆放
// 定义货物信息结构体
struct CargoInfo
public float length;
public float width;
public float height;
public float weight;
public Vector3 position; // 货物位置
public Quaternion rotation; // 货物旋转方向
public CargoState state; // 货物状态
// 使用Brute Force算法进行货物摆放
void BruteForceAlgorithm()
// 获取所有货物的信息
List<CargoInfo> cargoList = GetCargoList();
// 所有可能的货物摆放情况列表
List<List<CargoInfo>> allLayouts = new List<List<CargoInfo>>();
// 遍历所有可能的货物排列组合
GenerateAllLayouts(cargoList, new List<CargoInfo>(), allLayouts);
// 找到符合要求的最优摆放方案
List<CargoInfo> bestLayout = FindBestLayout(allLayouts);
// 将最优方案的货物摆放到卡车上
PlaceCargoToTruck(bestLayout);
// 生成所有可能的货物排列组合
void GenerateAllLayouts(List<CargoInfo> cargoList, List<CargoInfo> currentLayout, List<List<CargoInfo>> allLayouts)
// 如果有货物无法摆放,直接返回
if (cargoList.Exists(c => c.state == CargoState.CannotBePlaced))
return;
// 如果当前方案已经包含所有货物,将其添加到所有方案列表中
if (currentLayout.Count == cargoList.Count)
allLayouts.Add(currentLayout);
return;
// 遍历所有未摆放的货物,尝试在不冲突的情况下进行摆放
foreach (CargoInfo cargo in cargoList)
if (cargo.state != CargoState.NotPlaced)
continue;
// 摆放货物
if (TryPlaceCargo(cargo, currentLayout))
// 递归生成下一个方案
GenerateAllLayouts(cargoList, currentLayout, allLayouts);
// 恢复货物状态,继续尝试其他摆放方式
RemoveCargoFromLayout(cargo, currentLayout);
// 尝试将货物摆放到当前方案中
bool TryPlaceCargo(CargoInfo cargo, List<CargoInfo> currentLayout)
// 判断货物是否可以放置在当前摆放方案中
bool canBePlaced = CanCargoBePlaced(cargo, currentLayout);
if (canBePlaced)
// 更新货物信息
cargo.state = CargoState.Placed;
cargo.position = CalculateCargoPosition(cargo, currentLayout);
cargo.rotation = CalculateCargoRotation(cargo, currentLayout);
// 将货物添加到当前方案中
currentLayout.Add(cargo);
else
// 标记货物为无法摆放
cargo.state = CargoState.CannotBePlaced;
return canBePlaced;
// 判断货物是否可以放置在当前摆放方案中
bool CanCargoBePlaced(CargoInfo cargo, List<CargoInfo> currentLayout)
// 判断货物是否超出卡车范围
if (!IsInsideTruck(cargo, currentLayout))
return false;
// 判断货物是否与已经摆放的货物有碰撞
if (IsCollidingWithOtherCargo(cargo, currentLayout))
return false;
// 判断货物是否超重或超体积
if (!IsWithinLimitations(cargo, currentLayout))
return false;
return true;
// 判断货物是否在卡车范围内
bool IsInsideTruck(CargoInfo cargo, List<CargoInfo> currentLayout)
// 计算货物摆放后的位置
Vector3 position = CalculateCargoPosition(cargo, currentLayout);
// 判断货物是否超出卡车范围
if (position.x < 0 || position.x + cargo.length > transform.localScale.x ||
position.y < 0 || position.y + cargo.height > transform.localScale.y ||
position.z < 0 || position.z + cargo.width > transform.localScale.z)
return false;
return true;
// 判断货物是否与已经摆放的货物有碰撞
bool IsCollidingWithOtherCargo(CargoInfo cargo, List<CargoInfo> currentLayout)
foreach (CargoInfo otherCargo in currentLayout)
if (otherCargo.state == CargoState.P
// 判断货物是否与其他货物有碰撞
if (IsColliding(cargo, otherCargo))
return true;
return false;
// 判断货物是否超重或超体积
bool IsWithinLimitations(CargoInfo cargo, List<CargoInfo> currentLayout)
// 计算当前方案中所有货物的重量和体积
float totalWeight = 0.0f;
float totalVolume = 0.0f;
foreach (CargoInfo otherCargo in currentLayout)
totalWeight += otherCargo.weight;
totalVolume += otherCargo.length * otherCargo.width * otherCargo.height;
// 判断是否超重或超体积
if (totalWeight + cargo.weight > maxTotalWeight || totalVolume + cargo.length * cargo.width * cargo.height > maxTotalVolume)
return false;
return true;
// 计算货物摆放位置
Vector3 CalculateCargoPosition(CargoInfo cargo, List<CargoInfo> currentLayout)
// 将货物放置在卡车上方
float height = 0.0f;
foreach (CargoInfo otherCargo in currentLayout)
height += otherCargo.height;
return new Vector3(Random.Range(0.0f, transform.localScale.x - cargo.length),
height,
Random.Range(0.0f, transform.localScale.z - cargo.width));
// 计算货物旋转方向
Quaternion CalculateCargoRotation(CargoInfo cargo, List<CargoInfo> currentLayout)
// 随机旋转货物
return Quaternion.Euler(0, Random.Range(0, 4) * 90, 0);
// 判断两个货物是否有碰撞
bool IsColliding(CargoInfo cargo1, CargoInfo cargo2)
// 计算两个货物的包围盒
Bounds bounds1 = new Bounds(cargo1.position + new Vector3(cargo1.length / 2.0f, cargo1.height / 2.0f, cargo1.width / 2.0f),
new Vector3(cargo1.length, cargo1.height, cargo1.width));
Bounds bounds2 = new Bounds(cargo2.position + new Vector3(cargo2.length / 2.0f, cargo2.height / 2.0f, cargo2.width / 2.0f),
new Vector3(cargo2.length, cargo2.height, cargo2.width));
// 判断两个包围盒是否有交叉部分
if (bounds1.Intersects(bounds2))
return true;
return false;
// 移除当前方案中的货物
void RemoveCargoFromLayout(CargoInfo cargo, List<CargoInfo> currentLayout)
currentLayout.Remove(cargo);
cargo.state = CargoState.NotPlaced;
// 找到符合要求的最优摆放方案
List<CargoInfo> FindBestLayout(List<List<CargoInfo>> allLayouts)
// TODO: 实现查找符合要求的最优摆放方案的功能
// 默认返回所有方案中的第一个方案
return allLayouts[0];
// 将货物摆放到卡车上
void PlaceCargoToTruck(List<CargoInfo> cargoList)
foreach (CargoInfo cargo in cargoList)
if (cargo.state == CargoState.Placed)
GameObject cargoObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
cargoObject.transform.localScale = new Vector3(cargo.length, cargo.height, cargo.width);
cargoObject.transform.position = cargo.position;
cargoObject.transform.rotation = cargo.rotation;
cargoObject.GetComponent<Renderer>().material.color = Random.ColorHSV();
cargoObject.transform.SetParent(transform);
// 获取所有货物的信息
List<CargoInfo> GetCargoList()
// TODO: 实现获取所有货物的信息的功能
// 返回一个空的货物列表
return new List<CargoInfo>();
// 使用Greedy Algorithm算法进行货物摆放
void GreedyAlgorithm()
// 选择一个数学模型算法
currentAlgorithm = Algorithm.Greedy;
// 获取所有货物的信息
List<CargoInfo> cargoList = GetCargoList();
// 计算所有货物的重心
Vector3 centerOfMass = CalculateCenterOfMass(cargoList);
// 设置货物的起始位置和旋转方向
foreach (CargoInfo cargo in cargoList)
cargo.position = centerOfMass + new Vector3(0, cargo.height / 2.0f, 0);
cargo.rotation = Quaternion.identity;
cargo.state = CargoState.NotPlaced;
// 生成所有摆放方案
List<List<CargoInfo>> allLayouts = GenerateAllLayouts(cargoList);
// 找到符合要求的最优摆放方案
List<CargoInfo> bestLayout = FindBestLayout(allLayouts);
// 将货物摆放到卡车上
PlaceCargoToTruck(bestLayout);
// 计算所有货物的重心
Vector3 CalculateCenterOfMass(List<CargoInfo> cargoList)
Vector3 centerOfMass = Vector3.zero;
float totalWeight = 0.0f;
foreach (CargoInfo cargo in cargoList)
centerOfMass += cargo.weight * (cargo.position + new Vector3(0, cargo.height / 2.0f, 0));
totalWeight += cargo.weight;
centerOfMass /= totalWeight;
return centerOfMass;
// 贪心数学模型算法
public class GreedyModel
// 按照体积从大到小排序,优先选择放置体积较大的货物
public static List<Goods> SortByVolume(List<Goods> goodsList)
return goodsList.OrderByDescending(goods => goods.Length * goods.Width * goods.Height).ToList();
// 按照重量从大到小排序,优先选择放置重量较大的货物
public static List<Goods> SortByWeight(List<Goods> goodsList)
return goodsList.OrderByDescending(goods => goods.Weight).ToList();
POJ 2923 Relocation 装车问题 状态压缩DP+01背包
题目链接:https://vjudge.net/contest/103424#problem/I
转载于:>>>大牛博客
题目大意:
有 n 个货物,并且知道了每个货物的重量,每次用载重量分别为c1,c2的火车装载,问最少需要运送多少次可以将货物运完。
解题分析:
物品个数最多是10个,可以用0和1分别表示物品是否被选中运送
假设有3个物品,那么可以用001表示当前这一次选择将第3个物品运走
那么,所有的状态可以用0~2^n-1对应的二进制数表示出来
对于上述每一种状态,选择其中可以一次运走的状态进行01背包
其中,所有位全部为1的二进制数表示背包总体积
每个物品的体积是该状态对应二进制数中1的个数
为了把物品全部运走,要选择一些状态把背包的1全部被填满
值得注意的是,因为一件物品不会被运2次,所以所有选取的状态应该是没有交集的
比如1001101和1110010是不行的,第一件物品被运了2次
然后为了使次数最小,可以将次数抽象成01背包中的物品价值,每种状态对应运送一次,价值是1
如何判断某种状态是否可以一次运走?
因为有2辆车,所以将要判断该状态是否能分成满足体积分别小于等于车体积的2份,
如何从十进制中取出该状态被选择的物体?
也就是将二进制中的1的位置取出来
利用 :>> :右移运算符 << 左移运算符 & 按位与运算符
假设有一个二进制数: x = 01101
那么将它右移2位 : x>>=2,他会变成 00011(移出位被丢弃,左边移出的空位或者一律补0,或者补符号位)
我们知道1的二进制数是最后一位为1其他全为0,如果某数的二进制从又往左数第2位是1,移位之后这个1
变成最后一位,和二进制只有最后一位是1的数字1&之后还是1,而如果某数的二进制从又往左数第2位是0
的话,和二进制只有最后一位是1的数字1&之后将是0(因为1除了最后一位其他位全为0,而该数移位后最后一位是0)
综上所述 (x>>i)&1可以判断x从右往左第i位是0还是1【同理(x&(1<<i))也可以判断】
知道怎么找到二进制数中1的位置基本状压的代码也不难懂了
#include<iostream> #include<algorithm> #include<string> #include<cstring> #include<cstdio> #include<cmath> #define mem(a,x) memset(a,x,sizeof(a)) #define inf 1<<30 using namespace std; const double PI = acos(-1.0); typedef long long LL; int state[1030]; int dp[1030]; bool vis[1005]; int n,v1,v2,tot; int c[12]; bool ok(int x)//判断一种状态是否可行(可以一次运走) { int sun = 0; mem(vis,0); vis[0] = 1; for (int i = 0;i < n;i++) { if ((x>>i)&1) { sun += c[i]; for (int j = v1;j >= c[i];j--) //这个真的非常巧妙 开始看半天都不懂,自己模拟一遍才懂 { //比如说此状态有c1、c2、c3,3个体积,第一次操作把体积c1标记为1, if (vis[j-c[i]]) //第二次操作把c2和c1+c2两种体积标记为1,第三次把c3和前面的组合标记为1, vis[j] = 1; //最后这些体积能组合成的所有体积就都被标记成了1 } } } if (sun > v1+v2)//装不下 return 0; //总体积小不代表一定装得下,拆分成2份要2份都装得下 for (int i = 0;i <= v1;i++) { if (vis[i]&&sun-i <= v2)//如果存在(i,sun-i)这样的组合 return 1; //满足i可以被v1装下(前面for循环是对于v1的,vis[i]表示体积i可以被v1装下),sun-i可以被v2装下 } return 0; } void init()//初始化找到满足条件的状态 { tot = 0; for (int i = 1;i < (1<<n);i++) { dp[i] = inf; if (ok(i)) state[tot++] = i; } } int main() { int T; cin>>T; int oo = 0; while (T--) { cin>>n>>v1>>v2; for (int i = 0;i < n;i++) scanf("%d",&c[i]); init(); int V = (1<<n) - 1;//V是n个1的二进制数 dp[0] = 0;//没有物品当然是0次运走 for (int i = 0;i < tot;i++) { for (int j = V;j >= 0;j--) { if (dp[j] == inf) continue; //原版的背包是dp[j] = min(dp[j],dp[j-c[i]]+w[i]) //但是显然二进制不好表示减,但是可以用|抽象加 //这就相当于背包改版成dp[j+c[i]] = min(dp[j+c[i]],dp[j] + w[i]) if ((j&state[i])==0) //当然2种状态不能有交集 { dp[j|state[i]] = min(dp[j|state[i]] ,dp[j] + 1); } } } printf("Scenario #%d:\n%d\n",++oo,dp[V]); if (T) puts(""); } return 0; }
2018-05-13
以上是关于C# 卡车装车示例的主要内容,如果未能解决你的问题,请参考以下文章
在 Anylogic 中,我如何为向多个客户交付订单的卡车建模
制作卡车和按钮以提高速度,通过 jQuery 使用 html/js 改变方向
2021 中青杯 A题:汽车组装车间流水线物料配送问题 赛题思路