本文主要介绍了C#使用回溯法解决背包问题,并结合实例分析了背包问题的描述和C#的解决方法。有需要的朋友可以参考一下。
本文阐述了用回溯法用C#解决背包问题的方法。分享给你,供你参考。如下所示:
背包问题描述:
给定一组物品,每个物品都有自己的重量和价格。在有限的总重量内,如何选择才能让物品总价最高?
实现代码:
使用系统;
使用系统。集合。泛型;
使用系统。文本;
命名空间机架
{
//要装入书包的货物节点
BagNode类
{
公共int标记;//商品编号,从0开始记。
公共int权重;//货物重量
公共int值;//货物价值
公共BagNode(int m,int w,int v)
{
mark=m;
重量=w;
值=v;
}
}
//根据商品的数量,建立相应的全二叉树,比如3个商品,需要建立一个15个节点的二叉树,共三层(根节点所在的那层标记为0)
类BulidFullSubTree
{
public static int treeNodeNum=0;//完整二叉树节点的总数
public int noleafNode=0;//满二叉树出叶节点和剩余非叶节点。
公共静态TreeNode[]TreeNode;//存储一个完整二叉树的所有节点的数组
公共build full subtree(int nodeNum)
{
treeNodeNum=Convert。ToInt32(数学。Pow(2,nodeNum 1)-1);
noleafNode=Convert。ToInt32(treeNodeNum - Math。Pow(2,nodeNum));
treeNode=new treeNode[treeNodeNum];
for(int I=0;i treeNodeNum我)
{
treeNode[I]=new treeNode(I . ToString());
//初始化二叉树的所有节点
}
for(int I=0;我不离开;我)
{
//建立节点之间的关系
treeNode[i]。left=treeNode[2 * I 1];
treeNode[i]。right=treeNode[2 * I 2];
treeNode[2 * i 1]。bLeftNode=true
//如果是左子,记住它的标识变量是true。
treeNode[2 * i 2]。bLeftNode=false
}
treeNode[0]。级别=0;//约定根节点的层数为0
//根据数组下标确定节点的层数
for(int I=1;I=2;我)
{
treeNode[i]。level=1;
}
for(int I=3;I=6;我)
{
treeNode[i]。level=2;
}
for(int I=7;i=14我)
{
treeNode[i]。level=3;
}
}
}
//使用回溯法找到最优解的类别
类别问题
{
public TreeNode[]TreeNode=bulidfull subtree . TreeNode;
//获取建立的二叉树
int maxWeiht=0;//背包最大承载量
int treeLevel=Convert。ToInt32(数学。地板(数学。log(bulidfullstree . treenodenum,2)))1;
//二叉树的最大层数
int[]optionW=new int[100];//存储最佳解决方案的数组
int[]optionV=new int[100];//存储最佳解决方案的数组
int I=0;//计数器,记录相应数组的下标
int midTw=0;//中间变量,存储程序回溯时的中间值。
int midTv=0;//中间变量,存储程序回溯时的中间值。
int midt w1=0;//中间变量,存储程序回溯时的中间值。
int midt v2=0;//中间变量,存储程序回溯时的中间值。
BagNode[]BagNode;//存储商品节点
string[]solution=new string[3];
//程序最终得到的最优解是分开存储的:最优值、总权重、路径。
//int[]best way=new int[100];
TraceNode[]option trace=new TraceNode[100];//存储路径path
public DealBagProblem(BagNode[]bagN,TreeNode[] treeNode,int maxW)
{
bagNode=bagN
maxWeiht=maxW
for(int I=0;我选择跟踪。长度;我)
{
//初始化路径数组对象
option trace[I]=new TraceNode();
}
}
//核心算法,回溯。
//cursor:指向二叉树下一个节点的指针;Tw:当前背包的重量;电视:当前背包的总价值
公共void回溯(TreeNode游标,int tw,int tv)
{
如果(光标!=null)//如果当前节点为空
{
midTv=电视;
midTw=tw
if (cursor.left!=null游标. right!=空)
//如果当前节点不是叶节点
{
//如果当前节点是根节点,分别处理其左右子树
if (cursor.level==0)
{
BackTrace(cursor.left,tw,TV);
BackTrace(cursor.right,tw,TV);
}
//如果当前节点不是根节点
如果(光标。级别0)
{
//如果当前节点是左孩子
if (cursor.bLeftNode)
{
//如果将当前货物放进书包而不会超过背包的承重量
if (tw bagNode[cursor.level - 1].权重=maxWeiht)
{
//记录当前节点放进书包
Optiontrace[i].mark=I;
Optiontrace[i].traceStr=" 1
tw=tw bagNode[cursor.level - 1].重量;
tv=tv bagNode[cursor.level - 1].价值;
if (cursor.left!=空)
{
//如果当前节点有左孩子,递归
BackTrace(cursor.left,tw,TV);
}
if (cursor.right!=空)
{
//如果当前节点有左、右孩子,递归
BackTrace(cursor.right,midTw,midTv);
}
}
}
//如果当前节点是其父节点的右孩子
其他
{
//记录当前节点下的台湾,电视当递归回到该节点时,以所记录的值开始向当前节点的右子树递归
midTv2=midTv
midTw1=midTw
Optiontrace[i].traceStr=" 0
if (cursor.left!=空)
{
BackTrace(cursor.left,midTw,midTv);
}
if (cursor.right!=空)
{
//递归所传递的midTw1与midTv2是先前记录下来的
BackTrace(cursor.right,midTw1,midt v2);
}
}
}
}
//如果是叶子节点,则表明已经产生了一个临时解
如果(光标。left==空游标。right==null)
{
//如果叶子节点是其父节点的左孩子
if (cursor.bLeftNode)
{
if (tw bagNode[cursor.level - 1].权重=maxWeiht)
{
Optiontrace[i].traceStr=" 1
tw=tw bagNode[cursor.level - 1].重量;
tv=tv bagNode[cursor.level - 1].价值;
if (cursor.left!=空)
{
BackTrace(cursor.left,tw,TV);
}
if (cursor.right!=空)
{
BackTrace(cursor.right,midTw,midTv);
}
}
}
//存储临时优解
选项V[i]=电视;
optionW[I]=tw;
我;
TV=0;
tw=0;
}
}
}
//从所得到的临时解数组中找到最优解
公共字符串[] FindBestSolution()
{
int最佳值=-1;//最大价值
int最佳权重=-1;//与最大价值对应的重量
int best mark=-1;//最优解所对应得数组编号(由我确定)
for(int I=0;我选择。长度;我)
{
如果(选项最佳价值
{
最佳值=optionV[I];
最佳标记=I;
}
}
最佳权重=选项w[最佳标记];//重量应该与最优解的数组下标对应
for(int I=0;我选择跟踪。长度;我)
{
if(选项trace[I].tracestr。长度==bagNode .长度==最佳标记)
{
//找到与最大价值对应得路径
解决方案[2]=Optiontrace[i].traceStr
}
}
解[0]=最佳重量级.ToString();
解[1]=最佳值.ToString();
返回解决方案;
}
}
班级计划
{
静态void Main(string[] args)
{
//测试数据(货物)
//Node[]bagNode=new Node[100];
//BagNode bagNode1=new BagNode(0,5,4);
//BagNode bagNode2=new BagNode(1,3,4);
//BagNode bagNode3=new BagNode(2,2,3);
//测试数据(货物)
BagNode bagNode1=新的巴格节点(0,16,45);
BagNode bagNode2=新的巴格节点(1,15,25);
BagNode bagNode3=新的巴格节点(2,15,25);
BagNode[]BagNode arr=new BagNode[]{ BagNode 1,bagNode2,BagNode 3 };
bulidfullstree bfs=new bulidfullstree(3);
//第3个参数为背包的承重
DealBagProblem DBP=new DealBagProblem(bagNodeArr,BulidFullSubTree.treeNode,30);
//找到最优解并将其格式化输出
dbp .回溯(bulidfullstree。treenode[0],0,0);
string[] reslut=dbp .FindBestSolution();
if (reslut[2]!=空)
{
控制台(控制台).WriteLine('该背包最优情况下的货物的重量为:{0}\n货物的最大总价值为:{1},摘要[0]。ToString()函数返回[1]。tostring();
控制台(控制台).写入行(" \ n ");
控制台(控制台).WriteLine('该最优解的货物选择方式为:{0},摘要[2]。tostring();
char[] r=摘要[2]。ToString().toraraarray();
控制台(控制台).WriteLine('被选择的货物有");
for(int I=0);巴格诺德尔家。长度;(一)
{
if (r[i]).ToString()=='1 ')
{
控制台(控制台).WriteLine('货物编号:{0},货物重量:{1},货物价值:{2},bagNodeArr[i].马克,巴格NodeArr[i].重量bagNodeArr[i].价值;
}
}
}
其他语句
{
控制台(控制台).WriteLine('程序没有找到最优解,请检查你输入的数据是否合适我的天);
}
}
}
//存储选择回溯路径的节点
公共类tracenode公用类别追踪节点
{
公共int mark//路径编号
公共字符串tracestr//所走过的路径(1)代表取,2代表舍)
公共跟踪节点(int m,字符串t)
{
马克=m;
tracestr=t;
}
公共TraceNode()
{
mark=-1;
trace str=';
}
}
//回溯所要依附的满二叉树
TreeNode类
{
公共树节点左;//左孩子指针
公共树节点权利;//右孩子指针
公共内部级别;//数的层,层数代表货物的标识
符号字符串://节点的标识,用其所在数组中的下标,如:"1"、"2"
公共bool bleftnode//当前节点是否是父节点的左孩子
公共TreeNode(TreeNode l、TreeNode r、int lev、string sb、bool ln)
{
左=l;
右=r;
水平=杠杆
symb=sb:
bleftnode=ln
}
公共TreeNode(字符串sb)
{
symb=sb:
}
}
}
希望本文所述对大家的页:1程序设计有所帮助。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。