装箱问题C语言实现(算法分析)
基于VC++的推箱子游戏设计与实现
本科毕业设计(论文)基于VC++的推箱子游戏设计与实现学院自动化学院专业电子信息科学与技术年级班别2008级(2)班学号**********学生姓名吕文财指导教师 ________张学习 ___ __2012年6月基于VC++的推箱子游戏的设计与实现吕文财自动化学院摘要近年来随着科技的飞速发展, Visual C++语言的应用正在不断深入。
Visual C++语言是当今国际上非常流行的计算机高级编程语言之一,它是面向对象的可视化集成编程系统。
它不但具有程序框架自动生成、灵活方便的类管理、代码编写和界面设计集成交互操作、可开发多种程序等优点,而且通过简单的设置就可使其生成的程序框架支持数据库接口、OLE2,WinSock网络、3D控制界面。
它更以自动编译功能和高级除错功能著称。
因此,广泛受到编程人员青睐。
不仅适合作为系统描述语言,也用来编写系统软件,还可以用来编写应用软件和设计游戏等。
本论文着重分析用Microsoft Visual C++语言实现一个较为简单的推箱子游戏,旨在介绍推箱子游戏的实现方法,并逐步介绍Microsoft Visual C++6.0图形编程的方法和技巧。
本设计通过主界面对话框类、关口选择对话框类、帮助对话框类三大类以及键盘操作模块、游戏规则模块、地图文件读取模块、背景音乐播放模块、地图绘制模块,共五大模块构成。
实现了任意关数选择、难度依次加大、游戏步数记录、背景音乐播放、游戏帮助、胜负判断等多个功能,采用图形函数的使用实现了一个完整的推箱子游戏界面,界面清晰可见。
关键词:推箱子,c++语言,模块,图形编程AbstractIn recent years, with the rapid development of science and technology, Visual C + + language application are continuously in depth. Visual C + + language is very popular on the current international advanced programming languages of the computer, it is an object-oriented programming system integration of visualization. It not only has the program frame automatically generate, flexible convenient class management, coding and interface design integration, can develop a variety of interactive operation procedures and other advantages, and through the simple Settings will be able to make its generated programming framework support database interface, OLE2, WinSock network, 3 D control interface. It more for automatic compiler function and senior debugging is famous for its function. Therefore, widely favored by programming staff. Not only for the system description language, which is also used to write the system software, can also be used to write application software and game design, etc.This paper focuses on analyzing with Microsoft Visual C + + language realize a relatively simple pushed box game, is to introduce the realization method of game pushed box, and gradually introduce Microsoft Visual C++ 6.0 graphics programming methods and techniques. This design through the main interface dialog box class, pass options dialog box class, help dialog box class three categories and keyboard module, the rules of the game module, map reading modules, background music files play module, map module, a total of five module. Realize the random number, the difficulty in turn off choice, the more steps, background music record game play, the game won more than judgement to help, the function, the use of graphics functions achieved a complete pushed box game interface, interface can be clearly seen.Key word: boxman, C++ language, modules, graphics programming目录1 绪论 (1)1.1课题研究的意义 (1)1.2国内外研究动态 (2)1.2.1推箱子游戏的研究动态 (2)1.2.2国内外研究现状及分析 (3)2 课题研究相关技术与分析 (6)2.1 Microsoft Visual C++6.0概述 (6)2.2 可行性研究与需求分析 (7)3 推箱子游戏的总体设计 (9)3.1推箱子游戏概述 (9)3.2 推箱子游戏的基本要求 (9)3.1.1 开发软件及硬件环境要求 (9)3.1.2 运行环境 (9)3.1.4 测试环境操作系统与硬件配置 (9)3.1.4 界面要求 (9)3.3 推箱子游戏具有的功能 (10)3.3 推箱子游戏系统设计 (11)3.3.1 推箱子游戏功能架构 (11)3.3.2 程序结构设计 (11)3.3.3 出错处理设计 (12)3.3.4 维护设计 (13)3.4游戏界面设计 (13)3.4.1 游戏主界面的设计 (13)3.4.2 游戏菜单结构的设计 (13)3.4.3 游戏中关口选择对话框的设计 (14)4 推箱子游戏的设计与实现 (15)4.1推箱子游戏的界面实现 (15)4.1.1 游戏菜单的实现 (15)4.1.2 游戏帮助对话框的实现 (16)4.1.3 游戏关口选择对话框的实现 (17)4.1.4 游戏播放背景音乐的实现 (19)4.2推箱子游戏的核心算法设计与实现 (19)4.2.1 地图文件读取模块的设计与实现 (19)4.2.2 地图绘制模块的设计与实现 (20)4.2.3 键盘操作模块的设计与实现 (22)4.2.4 游戏规则模块的设计与实现 (23)4.2.5 主对话框的设计与实现 (24)5 推箱子游戏的整合测试 (25)5.1 主菜单和界面显示功能的测试演示 (25)5.2 键盘操作功能的测试演示 (25)5.3 箱子放置到指定位置时变色显示功能的测试演示 (26)5.4 支持地图扩展功能的测试演示 (27)5.5 游戏胜负判断功能的测试演示 (28)5.6 游戏帮助功能的测试演示 (29)总结 (31)参考文献 (32)致谢 (33)1 绪论1.1课题研究的意义目前,在中国乃至世界,游戏产业已经逐渐成为微控制器领域的一个相当庞大以及重要的分支,而关于这方面的高级人才却仍甚是缺乏。
装箱计算公式
装箱计算公式嘿,咱们今天来聊聊装箱计算公式这个看似有点枯燥,但其实挺有意思的话题。
要说装箱计算公式,那咱们得先从生活中的一个小场景说起。
就说前段时间我去超市买水果,那种成箱装的水果。
我就好奇啊,这商家是怎么把一堆大小不一的水果,整整齐齐地装进箱子里,还能保证空间利用最大化的呢?其实啊,装箱计算公式就是用来解决这类问题的。
它就像是一个魔法公式,能告诉我们怎么在有限的空间里,装下最多的东西。
比如说,一个长方体形状的箱子,长、宽、高分别是 a、b、c,要装一些同样是长方体形状的小物件,小物件的长、宽、高分别是x、y、z。
那能装下的小物件数量 N 就可以通过这样的公式来计算:N =([a/x]×[b/y]×[c/z])。
这里的中括号 [ ] 表示向下取整,就是说不管小数部分是多少,都只取整数部分。
听起来有点复杂?咱们举个具体的例子。
假设箱子的长是50 厘米,宽 30 厘米,高 20 厘米,小物件的长 10 厘米,宽 8 厘米,高 5 厘米。
那按照公式来算,能装下的数量就是:([50/10]×[30/8]×[20/5])=(5×3×4)= 60 个。
但实际情况往往没这么简单。
因为物件的形状可能不规则,或者有些空隙没办法完全利用。
就像我买的那箱水果,有的水果稍微有点突出,有的地方就空了一点。
还有的时候,我们不仅要考虑能装多少,还要考虑怎么装更稳当,怎么装不容易损坏物品。
比如装易碎品,可能就得在周围多留点缓冲空间。
而且啊,装箱计算公式在不同的行业里,应用还不太一样。
在物流行业,要考虑货物的重量分布,保证运输过程中的平衡;在工厂生产线上,要快速计算出装箱数量,提高生产效率。
想象一下,一个工厂里,成千上万的零件等着装箱发货,如果没有准确的装箱计算公式,那得多乱套啊!可能会浪费好多箱子,增加成本;也可能装得不稳当,运输途中出问题。
再回到咱们生活中,搬家的时候是不是也得考虑怎么把东西装箱更合理?把大大小小的家具、衣物、杂物都装进去,还不能太挤,也不能太空。
贪心算法之装箱问题
贪⼼算法之装箱问题问题描述装箱问题可简述如下:设有编号为 0、1、…、n - 1 的 n 种物品,体积分别为v0、v1、…、vn-1。
将这 n 种物品装到容量都为 V 的若⼲箱⼦⾥。
约定这 n 种物品的体积均不超过 V,即对于 0≤ i<n,有 0<vi ≤ v。
不同的装箱⽅案所需要的箱⼦数⽬可能不同。
装箱问题要求使装尽这 n 种物品的箱⼦数要少。
贪⼼求解使⽤⼀种贪⼼策略:每次都想将当前体积最⼤的物品装⼊箱中,在这块类似于这个问题 ->>>其实在⽣活中这也是很常见的⼀种做法,在没有充⾜时间去考虑如何最优解决这类问题时直觉(第六感狗头保命)告诉我们可以这么去试试。
更直接的⼀个例⼦,⼒扣上有这么⼀道题:在柠檬⽔摊上,每⼀杯柠檬⽔的售价为 5 美元。
顾客排队购买你的产品,(按账单 bills ⽀付的顺序)⼀次购买⼀杯。
每位顾客只买⼀杯柠檬⽔,然后向你付 5 美元、10 美元或20美元。
你必须给每个顾客正确找零,也就是说净交易是每位顾客向你⽀付 5 美元。
注意,⼀开始你⼿头没有任何零钱。
注:上⾯⿊体部分内容引⾃很明显,当客户给我们$20进⾏找零时,⾃然⽽然地就给ta找了⼀张$10加上⼀张$5,为什么这么做?⾯对$20,我们有两种⽅案可以使⽤:找三张$5给顾客找⼀张$10 以及⼀张 $5 给顾客选择第⼆种⽅案的原因对于做⽣意的⽼板应该不陌⽣,营业过程中我们需要备上⼀部分零钱在交易时⽅便找零,不⾄于出现⽆法找零的尴尬局⾯,这是商⼈们所想的,在上题中也同样适⽤。
但贪⼼算法的弊端也很明显:不考虑之前解带来的影响,仅仅为了达到当前最优解,这样”⼀根筋“的策略也不能在任何情况下得到最优解。
如只有⾯值分别为 1、5 和 11 单位的硬币,⽽希望找回总额为 15 单位的硬币。
按贪婪算法,应找 1 个 11 单位⾯值的硬币和 4 个 1 单位⾯值的硬币,共找回 5 个硬币。
但最优的解应是 3 个 5 单位⾯值的硬币。
单一尺寸长方体三维装箱问题的一种求解算法
单一尺寸长方体三维装箱问题的一种求解算法单一尺寸长方体三维装箱问题是一种经典的组合优化问题,常常出现在物流、包装、生产等领域中。
该问题的目的是将一系列商品(通常为长方体)尽可能地装箱,使得所需要的箱子最少,同时避免商品之间的重叠或者空隙。
为了解决这个问题,我们可以采取下面的求解算法:1. 构建三维坐标系。
为了方便表示商品的位置和箱子的大小,我们需要构建一个三维坐标系。
假设我们的货物都是长方体,那么我们需要知道每个长方体的长、宽、高以及重量,以便于计算重心和位置。
同时,我们还需要确定我们的箱子大小,可以根据需要调整大小,从而适应货物的大小。
在确定每个长方体的位置之前,首先要确定它们之间的相对位置,这样可以决定它们之间是否存在空隙或者重叠。
2. 选择一种合适的装箱算法。
目前常用的装箱算法有贪心算法、回溯算法、遗传算法等,其中贪心算法的效率较高,但是不能保证得到最优解;回溯算法可以得到最优解,但是效率较低;遗传算法则是一种高效的启发式算法,可以保证得到比较优的解。
在实际应用中可以根据需要选择不同的算法。
3. 将长方体逐个装入箱子。
为了尽量减少使用的箱子数量,我们需要将每个长方体按照一定规则装入箱子中。
一种常用的方式是通过二叉树来表示盒子。
假设我们需要装入n个长方体,我们从第一个长方体开始往箱子中放。
此时我们将先选取一个长方体,作为根节点,并将其放入一个空盒子中。
接下来,我们将每一个长方体都放入箱子中,直到所有的长方体都被装入箱子中,或者已经没有可以放入的长方体。
在放置长方体的过程中,我们需要遵循一定的规则,例如优先放置最大/最小的长方体或者根据某些贪心策略来选择放置位置和方向。
4. 调整长方体位置。
在将长方体放入箱子中之后,我们需要检查是否存在重叠或者空隙。
如果存在,则需要对长方体进行一定的调整,例如旋转或移动。
在调整长方体位置的过程中,需要根据长宽高等因素,以及已经放置的长方体的位置和方向等因素,来确定合适的位置和方向,以尽量减少空隙和重叠。
C语言实现推箱子游戏完整代码
C语⾔实现推箱⼦游戏完整代码C语⾔实现推箱⼦游戏完整代码,供⼤家参考,具体内容如下前⾔⾃⼰做的,可能有些代码不够⼯整,或者有些⼩问题,但游戏的基本操作是可以实现的代码效果代码⼀共分为8个部分,4个控制上下左右移动,2个判断输赢,1个统计归为的个数,⼀个作图。
⼿动设置地图⽤'0'表⽰空格,“1”表⽰墙,“2”表⽰箱⼦,“3”表⽰⼈,“4”表⽰终点这样可以提⾼代码的移植性如需改为⼿动输⼊地图可以直接定义⼀个⼆维数组,在给他赋值就可以了int screen[9][11]={{0,1,1,1,1,1,1,1,1,0,0},{0,1,0,0,0,1,0,0,0,1,0},{0,1,0,2,2,2,2,2,0,1,0},{0,1,0,2,0,2,0,2,0,1,1},{0,1,0,0,0,3,0,0,2,0,1},{1,1,0,1,1,1,1,0,2,0,1},{1,0,4,4,4,4,4,1,0,0,1},{1,0,4,4,4,4,4,0,0,1,1},{1,1,1,1,1,1,1,1,1,1,0}};//定义为全局变量(地图) i表⽰⾏,j表⽰列计算地图中终点的个数这⼀步主要是为了后⾯判断游戏输赢的int cum(){int i,j,k=0;for(i=0;i<9;i++){for(j=0;j<11;j++){if(screen[i][j]==2){k++;}}}//遍历整个⼆维数组return k;}//计算地图中有多少个终点打印地图函数通过switch函数对⼆维数组中的值进⾏可视化,也就是画出地图注意:这⾥还定义出了6和7,是通过重叠的关系来算的,就是箱⼦在终点上,这个位置⼜有箱⼦⼜有终点2个标识,所以让两个的数值加起来,⽅便理解,也⽅便后⾯的计算void print(){int i,j;printf("请⽤wsad代表上下左右来进⾏游戏\n");for(i=0;i<9;i++){for(j=0;j<11;j++){switch(screen[i][j]){case 0:printf(" ");//空break;case 1:printf("■");//墙break;case 2:printf("★");//箱⼦break;case 3:printf("♀");//⼈break;case 4:printf("○");//终点break;case 6:printf("★");break;//箱⼦和终点case 7://⼈和终点显⽰⼈printf("♀");break;}}printf("\n");}}判断游戏输赢这⾥我写了2个函数,⼀个判断赢,⼀个判断输,并返回值,然后在主函数的最后⾯通过判断返回值来确定游戏的输赢判断赢int win(){int i,j,k=0;int t=0;for(i=0;i<9;i++){for(j=0;j<11;j++){if(screen[i][j]==6){k++;}}}//遍历整个⼆维数组,计算箱⼦在终点上的个数if(k==cum()){t=1;}//如果个数等于前⾯计算出的终点个数,则说明所有终点都放了箱⼦,说明游戏胜利return t;} //判断赢判断输int lose(){int i,j;int k=0;for(i=0;i<9;i++){for(j=0;j<11;j++){if(i>0 && j>0 ){if(screen[i][j] == 2 || screen[i][j] == 6){if(((screen[i-1][j] == 1 || screen[i-1][j] == 2 || screen[i-1][j] == 6) && (screen[i][j-1] == 1 || screen[i][j-1] == 2 || screen[i][j-1] == 6))|| ((screen[i][j-1] == 1 || screen[i][j-1] == 2 || screen[i][j-1] == 6) && (screen[i+1][j] == 1 || screen[i+1][j] == 2 || screen[i+1][j] == 6))|| ((screen[i+1][j] == 1 || screen[i+1][j] == 2 || screen[i+1][j] == 6) && (screen[i][j+1] == 1 || screen[i][j+1] == 2 || screen[i][j+1] == 6))|| ((screen[i][j+1] == 1 || screen[i][j+1] == 2 || screen[i][j+1] == 6) && (screen[i-1][j] == 1 || screen[i-1][j] == 2 || screen[i-1][j] == 6))){k++;}}}}/*这⾥也是遍历了整个数组,判断所有的箱⼦四个⽅向的情况,如果有三个⽅向被堵住了说明箱⼦⽆法移动了,也表明这个箱⼦失效了,⽤k来记录失效的个数,当全部失效时游戏失败(这是游戏的玩法,其实有⼀个被堵住就已经不可能胜利了)*/}if(k==cum()){k=1;return k;//返回1说明游戏失败}接下来是最重要的四个控制函数向上移动通过数字的变化来控制⼆维数组的变化,进⽽控制地图的更新这⾥⾮常重要的就是要理解:加1,加2,加3减3都是什么意思加1:箱⼦的值是2,⼈的值是3,所以箱⼦的位置变成⼈需要加1来实现加2:空地的值是0,箱⼦的值是2,箱⼦和终点在⼀起的值是6,所以在推箱⼦的时候,前⽅的空格或者终点放上箱⼦后数值会加2加3减3:⼈的值是3,⼈要动的话,它原先在的格⼦就会因为⼈⾛了导致数值减3,⾛到的那个格⼦就会因为站了⼈⽽加3如果这个理解的话,代码就⾮常简单了void movew(){if(x>0){if(screen[x-1][y]==1){return ;/*如果箱⼦的上⾯是墙,则地图不会发⽣变化,因为推不动嘛*/}else if(screen[x-1][y]==0){screen[x-1][y]+=3;screen[x][y]-=3;x--;/*如果前⾯是空地,则需要向前移动⼀格,也就是原先⼈的位置变成空地,前⽅的空地变成⼈,空地(0)变成⼈(3)需要加3,⼈变成空地需要减3*/}else if(screen[x-1][y]==4){screen[x-1][y]+=3;screen[x][y]-=3;x--;}//⼀样的else if(screen[x-1][y]==2||screen[x-1][y]==6){if(screen[x-2][y]==0){screen[x-2][y]+=2;//箱⼦前⾯的格变成箱⼦(2)screen[x-1][y]+=1;//箱⼦的位置变成⼈(3)screen[x][y]-=3;/*如果前⾯是空地,则需要向前移动⼀格,也就是原先是箱⼦的格⼦变成⼈,⼈的位置变成空地,原先的空地变成箱⼦,箱⼦(2)变成⼈(3)需要减3,空地变成⼈*/x--;}else if(screen[x-2][y]==1){return ;}else if(screen[x-2][y]==2){return;//如果箱⼦的前⾯是墙或者其他的箱⼦,则箱⼦推不动}else if(screen[x-2][y]==4){screen[x-2][y]+=2;screen[x-1][y]+=1;screen[x][y]-=3;x--;}//这个情况别漏了}}}其他三个⽅向的代码思路和这个是⼀样的向下移动void moves(){if(x<9){if(screen[x+1][y]==1){return ;}else if(screen[x+1][y]==0){screen[x+1][y]+=3;screen[x][y]-=3;x++;}else if(screen[x+1][y]==4){screen [x+1][y]+=3;screen[x][y]-=3;}else if(screen[x+1][y]==2||screen[x+1][y]==6){ if(screen[x+2][y]==1){return;}else if(screen[x+2][y]==0){screen[x+2][y]+=2;screen[x+1][y]+=1;screen[x][y]-=3;x++;}else if(screen[x+2][y]==2){return ;}else if(screen[x+2][y]==4){screen[x+2][y]+=2;screen[x+1][y]+=1;screen[x][y]-=3;x++;}}}}向左移动void movea(){if(y>0){if(screen[x][y-1]==1){return;}else if(screen[x][y-1]==4){screen[x][y-1]+=3;screen[x][y]-=3;y--;}else if(screen[x][y-1]==0){screen[x][y-1]+=3;screen[x][y]-=3;y--;}else if(screen[x][y-1]==2||screen[x][y-1]==6){ if(screen[x][y-2]==0){screen[x][y-2]+=2;screen[x][y-1]+=1;screen[x][y]-=3;y--;}else if(screen[x][y-2]==1){return;}else if(screen[x][y-2]==2){return;}else if(screen[x][y-2]=4){screen[x][y-2]+=2;screen[x][y-1]+=1;screen[x][y]-=3;y--;}}}}向右移动void moved(){if(y<9){if(screen[x][y+1]==1){return;}else if(screen[x][y+1]==4){screen[x][y+1]+=3;screen[x][y]-=3;y++;}else if(screen[x][y+1]==0){screen[x][y+1]+=3;screen[x][y]-=3;y++;}elseif(screen[x][y+1]==2||screen[x][y+1]==6){if(screen[x][y+2]==0){screen[x][y+2]+=2;screen[x][y+1]+=1;screen[x][y]-=3;y++;}else if(screen[x][y+2]==4){screen[x][y+2]+=2;screen[x][y+1]+=1;screen[x][y]-=3;y++;}else if(screen[x][y+2]==2){return;}else if(screen[x][y+2]==1){return;}}}}主函数这个主函数写的有点乱,直接看注释吧int main(){int n,t;int j,k;int b=1;here:system("cls");//printf("开始游戏请按1\n退出游戏请按2\n");scanf("%d",&j);if(j==1){printf("请⽤wsad代表上下左右来进⾏游戏\n");//这个就引导进⼊游戏while(1){system("cls");/*在每⼀次移动过后都清除上⼀个地图,不然就会每⾛⼀步⽣成⼀个图*/print();//先打印地图scanf("%c",&n);//读⼊⽤户的操作switch(n){case 'w':movew();break;case 's':moves();break;case 'a':movea();break;case 'd':moved();break;} //控制⼈移动t=win();if(t==1){goto there;}//每次操作完先判断游戏是否胜利,如果胜利了直接跳到函数最后if(b == lose()){system("cls");print();printf("游戏失败");return 0;} //游戏失败提⽰}}else {system("cls");printf("您确认要退出游戏吗\n确认退出按1\t返回上⼀层按2\n");scanf("%d",&k);if(k==1){printf("你已退出游戏,期待你的再次到来,谢谢");return 0;}else {goto here;}}//这⼀块是最前⾯⽤户进⼊游戏那⾥的,如果⽤户选择退出游戏执⾏的操作 there:printf("恭喜你通过了游戏!");return 0;}//主函数所有的代码就到这⾥了,如果需要完整代码可以留⾔以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
c语言算法--贪婪算法---01背包问题
c语言算法--贪婪算法---0/1背包问题在0 / 1背包问题中,需对容量为c 的背包进行装载。
从n 个物品中选取装入背包的物品,每件物品i 的重量为wi ,价值为pi 。
对于可行的背包装载,背包中物品的总重量不能超过背包的容量,最佳装载是指所装入的物品价值最高,即n ?i=1pi xi 取得最大值。
约束条件为n ?i =1wi xi≤c 和xi?[ 0 , 1 ] ( 1≤i≤n)。
在这个表达式中,需求出xt 的值。
xi = 1表示物品i 装入背包中,xi =0 表示物品i 不装入背包。
0 / 1背包问题是一个一般化的货箱装载问题,即每个货箱所获得的价值不同。
货箱装载问题转化为背包问题的形式为:船作为背包,货箱作为可装入背包的物品。
例1-8 在杂货店比赛中你获得了第一名,奖品是一车免费杂货。
店中有n 种不同的货物。
规则规定从每种货物中最多只能拿一件,车子的容量为c,物品i 需占用wi 的空间,价值为pi 。
你的目标是使车中装载的物品价值最大。
当然,所装货物不能超过车的容量,且同一种物品不得拿走多件。
这个问题可仿照0 / 1背包问题进行建模,其中车对应于背包,货物对应于物品。
0 / 1背包问题有好几种贪婪策略,每个贪婪策略都采用多步过程来完成背包的装入。
在每一步过程中利用贪婪准则选择一个物品装入背包。
一种贪婪准则为:从剩余的物品中,选出可以装入背包的价值最大的物品,利用这种规则,价值最大的物品首先被装入(假设有足够容量),然后是下一个价值最大的物品,如此继续下去。
这种策略不能保证得到最优解。
例如,考虑n=2, w=[100,10,10], p =[20,15,15], c = 1 0 5。
当利用价值贪婪准则时,获得的解为x= [ 1 , 0 , 0 ],这种方案的总价值为2 0。
而最优解为[ 0 , 1 , 1 ],其总价值为3 0。
另一种方案是重量贪婪准则是:从剩下的物品中选择可装入背包的重量最小的物品。
三维装箱问题算法
三维装箱问题算法一、问题概述三维装箱问题是一种经典的优化问题,涉及到在有限的空间内放置多个物体,以满足一定的约束条件并最大化空间利用率。
在这个问题中,我们考虑一个三维盒子,其中可以放置一定数量的物体,每个物体都有一定的体积,我们需要找到一种放置方式,使得盒子的剩余空间最小。
二、算法介绍为了解决三维装箱问题,我们可以使用多种算法,其中一种常用的算法是遗传算法。
遗传算法是一种基于生物进化原理的优化算法,通过模拟自然选择和遗传机制来寻找问题的最优解。
具体步骤如下:1. 初始化:随机生成一组装箱方案,作为种群。
2. 评估:对每个装箱方案进行评估,计算剩余空间的大小。
3. 选择:根据每个装箱方案的剩余空间大小,选择出适应度较高的方案作为父代。
4. 交叉:对父代进行交叉操作,生成新的子代。
5. 变异:对子代进行变异操作,以增加种群的多样性。
6. 终止条件:当满足终止条件(如达到最大迭代次数或找到满足要求的解)时,停止算法,输出当前最优解。
三、算法实现下面是一个简单的遗传算法实现示例,使用Python语言编写:```pythonimport numpy as np# 定义适应度函数def fitness(solution):remaining_space = np.prod(solution) -np.prod(np.delete(solution, axis=0))return remaining_space# 初始化种群population = np.random.randint(low=1, high=10, size=(pop_size, 3)) # 迭代进化for generation in range(max_generations):# 评估种群中每个装箱方案的适应度fitness_values = np.apply_along_axis(fitness, axis=1,arr=population)# 选择适应度较高的方案作为父代parents = np.argmax(fitness_values, axis=0)# 进行交叉和变异操作offspring = crossover(population, parents)population = offspring + np.random.randint(low=-1, high=1, size=offspring.shape, dtype=np.int32)# 输出当前最优解和最优解的适应度值if generation % print_freq == 0:best_solution = np.argmin(fitness_values)best_fitness = fitness_values[best_solution]print(f"Generation {generation}: Best solution:{best_solution}, Best fitness: {best_fitness}")# 判断是否达到终止条件,如果是则输出最终结果if best_fitness <= optimal_fitness:break```以上代码实现了一个简单的遗传算法,通过交叉和变异操作生成新的种群,并在每一代选择适应度较高的方案作为父代进行繁殖,最终得到最优解。
装箱问题
J1
J2
J3 J4
J5
J6
对于 J3 , 先检查 B1 是否能
容纳下, 能 . 所以将 J3 放 入 B1,…
J3
J4
J1
J2
J5
J6 B4 B5
解为:
B1
B2
B3
x11 x22 x13 x24 x35 x46 1 其余为零,zFF ( I ) 4.
一般地,J1,…,Jj 已放入 B1,…,Bi 箱子,对于 Jj+1,
则依次检查 B1,B2,…,Bi,将 Jj+1 放入首先找到的能 放得下的箱子,如果都放不下,则启用箱子 Bi+1 ,将 Jj+1 放入 Bi+1 ,如此继续,直到所有物品装完为止 . 特点: 1、按物品给定的顺序装箱; 2、对于每个物品 Jj 总是放在能容纳它的具
Corollary 3.1
记 L2 max L(a) 0 a C 2 , a 为整数
则 L2 是装箱问题的最优解的一个下界,且 L2 L1 . Proof : L2 为最优解的下界是显然的 .
(若证明 L(0) L1 ,则可得 L2 L1 )
§2
n wi i 1 Theorem 3.1 BP 最优值的一个下界为 L1 C . a 表示不小于 a 的最小整数.
装箱问题的最优解值下界
Theorem 3.2 设 a 是任意满足 0 a C 2 的整数,对 BP 的任一实例 I , 记 I1 物品 j w j C a ,
C
个箱子中第一个物品,因此这两个箱子中物品的总长度
大于 C ,所以前 2k 个箱子中物品的总长度大于 Ck . n z (I ) wi Ck 矛盾 . NF 这与 2, 从而 RNF 2. i 1 zopt ( I ) 1 1 1 1 1 1 w1 , w2 ,, w4 N , , , ,, , 考虑实例 I : C = 1, 2 2N 2 2N 2 2N
【数据结构】--C++实现箱子装箱问题
【数据结构】--C++实现箱⼦装箱问题⼀、问题描述①在箱⼦装载问题中,有若⼲个容量为c的箱⼦和n个待装载⼊箱⼦中的物品。
物品i需占是s[i]个单元(0<s[i]<=c)。
所谓成功装载(feasible packing),是指能把所有物品都装⼊箱⼦⽽不溢出,⽽最优装载(optimal packing)是指使⽤了最少箱⼦的成功装载。
对于箱⼦装载问题,有4种流⾏的求解算法。
②基本要求:->n依次取100,200,500,1000,⽐较以上四种⽅法(在时间上和所⽤箱⼦的数量上)的性能。
->FF,FFD⽅法使⽤竞赛树结构,BF,BFD使⽤⼆叉搜索树结构。
⼆、需求描述1.4种流⾏的求解算法:<1>最先匹配法(FF):物品按1,2...,n的顺序装⼊箱⼦。
假设箱⼦从左⾄右排列,每⼀物品i放⼊可盛载它的最左箱⼦。
<2>最先匹配递减法(FFD):⽅法与FF类似,区别在于各物品⾸先按容量递减的次序排列,即对于1<=i<n,有s[i]>=s[i+1].<3>最优匹配法(BF):设c[j]为箱⼦j的可⽤容量,初始时,所有箱⼦的可负载容量为c。
物品i放⼊具有最⼩c且容量⼤于s[i]的箱⼦中。
<4>最优匹配递减法(BFD):⽅法与BF相似,区别在于各物品⾸先按容量递减的次序排列,即对于1<=i<n,有s[i]>=s[i+1].2.输⼊要求:①第⼀种输⼊⽅式:n在程序中固定读⼊100,200,500,1000个数,这些数预先在⽂本中⼿动输⼊为固定的⽆序正整数。
②第⼆种输⼊⽅式:n为程序运⾏后,⼈为输⼊的数n,并且⽣成n个随机数,⽤作程序所需要测试的物品⼤⼩数。
3.输出要求:输出的要求为:直观的分析排列出在不同的箱⼦数量、不同的物品数量以及不同的物品⼤⼩的情况下,上述四种⽅法在时间上和所⽤的箱⼦的数量上的不同。
⽐较四种⽅法的性能。
算法分析与设计习题集
序号项目名称任务描述设计要求1. C语言词法分析算法设计与实现编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。
输入:一段C语言程序输出:每个单词以及每个单词所在行号比如:输入如下一段C程序main(){int a,b;}输出为:( mian, ”line=1”);( ( , ”line=1“);( ) , ”line=1”);({ , ”line=2”);( int, “line=2”);……………用Java语言,或者C语言,推荐用Java语言。
完成所要有的C语言词法分析器。
要求:读文件,或者命令行的形式读取C源程序,输出源程序中每个单词以及每个单词所在行号。
要求:开发出图形化界面,读文件,把结果输出到界面上。
2.行程编码的设计与实现Run-Length Encoding(RLE)行程长度的原理是将一扫描行中的颜色值相同的相邻像素用一个计数值和那些像素的颜色值来代替。
例如:aaabccccccddeee,则可用3a1b6c2d3e来代替。
对于拥有大面积,相同颜色区域的图像,用RLE压缩方法非常有效。
算法输入:图像算法输出:图像行程编码序列利用C语言,或者Java语言,完成算法对图像的行程编码.设计一个GUI界面,能够接受图像,输出图像的形成编码序列3.特征权重排序信息增益算法的设计与实现在文本分类领域中,信息增益IG是一种常用的特征排序算法的标准。
要求利用信息增益公式计算每个特征的信息增益值,并根据信息增益值从大到小输出。
举例如下:假设文本中包括的特征:outlook {sunny, overcast, rainy}// 晴天、多云、下雨temperature {hot, mild, cool} // 热、温和的、冷humidity {high, normal} // high表示潮湿、normal表示正常windy {Strong, weak} // TRUE表示有风、FALSE表示无风play {yes, no} yes表示打网球,no表示不打网球假设有14个样本如下:1 , Sunny , Hot , High , Weak , No2 , Sunny , Hot , High , Strong , No3 , Overcast , Hot , High , Weak , Yes利用Java语言实现样本中特征信息增益的计算,然后根据信息增益值从大到小排序。
二维装箱问题的算法
二维装箱问题(2D Bin Packing Problem)是一个经典的组合优化问题,它的目标是将一系列的矩形物品放入最小数量的容器中,同时满足每个容器的尺寸限制。
这个问题在实际应用中有很多场景,如物流、仓储、广告排版等。
解决二维装箱问题的算法有很多,以下是一些常见的算法:1. 贪心算法(Greedy Algorithm):贪心算法是一种简单且易于实现的算法。
它的基本思想是在每一步都选择当前最优的解决方案。
对于二维装箱问题,贪心算法可以选择每次放入面积最大的矩形,直到无法再放入为止。
然后开始新的一行,重复这个过程。
贪心算法的缺点是可能得不到最优解,因为它没有考虑到后续的放置情况。
2. 启发式算法(Heuristic Algorithm):启发式算法是一种基于经验的算法,它通过一定的规则来指导搜索过程。
对于二维装箱问题,启发式算法可以根据矩形的长宽比、面积等因素来确定放置的顺序和位置。
启发式算法通常能够得到较好的解,但不一定是最优解。
3. 遗传算法(Genetic Algorithm):遗传算法是一种模拟自然选择和遗传机制的全局搜索算法。
它通过不断地进行交叉、变异和选择操作,来生成新的解决方案。
对于二维装箱问题,遗传算法可以用于优化矩形的放置顺序和位置,以找到更优的解。
4. 模拟退火算法(Simulated Annealing):模拟退火算法是一种基于概率的全局优化算法。
它通过在一定的温度下随机搜索解空间,并在温度降低时逐渐收敛到最优解。
对于二维装箱问题,模拟退火算法可以用于优化矩形的放置顺序和位置,以找到更优的解。
5. 粒子群优化算法(Particle Swarm Optimization):粒子群优化算法是一种基于群体智能的全局优化算法。
它通过模拟鸟群觅食行为,来寻找最优解。
对于二维装箱问题,粒子群优化算法可以用于优化矩形的放置顺序和位置,以找到更优的解。
6. 线性规划(Linear Programming):线性规划是一种数学优化方法,它可以用于求解具有线性约束和目标函数的问题。
回溯法解决集装箱问题c语言程序
回溯法解决集装箱问题c语言程序集装箱问题是一个经典的组合优化问题,其目标是找到一种最优的方式将一组不同大小的集装箱装入一艘货船中。
在这个问题中,我们需要考虑集装箱的尺寸、重量以及货船的容量限制。
回溯法是一种常用的解决组合优化问题的方法,下面我们将介绍如何使用C语言编写回溯法解决集装箱问题的程序。
首先,我们需要定义一个结构体来表示集装箱的属性,包括尺寸和重量。
代码如下:```ctypedef struct {int size;int weight;} Container;```接下来,我们需要定义一个函数来计算货船的最大装载量。
这个函数将采用回溯法的思想,通过递归的方式遍历所有可能的装载方式,并返回最优解。
代码如下:```cint maxLoad(Container containers[], int n, int capacity, int index, int currentSize, int currentWeight) {// 如果已经遍历完所有集装箱,返回当前的装载重量if (index == n) {return currentWeight;}// 如果当前集装箱的尺寸或重量超过了货船的容量限制,跳过该集装箱if (currentSize + containers[index].size > capacity || currentWeight + containers[index].weight > capacity) {return maxLoad(containers, n, capacity, index + 1, currentSize, currentWeight);}// 尝试将当前集装箱装入货船int load = maxLoad(containers, n, capacity, index + 1, currentSize + containers[index].size, currentWeight + containers[index].weight);// 尝试不将当前集装箱装入货船int notLoad = maxLoad(containers, n, capacity, index + 1, currentSize, currentWeight);// 返回装载重量较大的方案return load > notLoad ? load : notLoad;}```最后,我们可以在主函数中调用上述函数来解决集装箱问题。
装箱问题算法实现讲解
装箱问题算法实现讲解有一个箱子容量为V(正整数,0≤V≤20000),同时有n个物品(0≤n≤30),每个物品有一个体积(正整数)。
要求从n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
[样例]输入:24 一个整数,表示箱子容量6 一个整数,表示有n个物品8 接下来n行,分别表示这n个物品的各自体积。
312797输出:0 一个整数,表示箱子剩余空间算法分析:本题是经典问题:0-1背包的特殊例子(加强了已知条件)。
用整形数组volume存储各件物品的体积,用布尔型函数h(i,k)表示前i个物品通过组合能否恰好装满容量k的空间,则考虑第i件物品,如果没有被选中,则问题转化为h(i-1,k);如果第i件物品被选中了,则问题转化为h(i-1,k-volume[i]),因此有如下的表达式:h(i,k)=h(i-1,k-volume[i]) || h(i-1,k);k从V开始递减,判断h(n,k)是否为真,第一个符号要求的k即为剩余空间最小时消耗的体积。
如果此时直接编写程序,就要定义一个二维数组,空间复杂度时n*v,注意到了n,v的取值范围很大,所以用二维数组存储就会有问题。
我们注意到,h(i,k)的取值仅与h(i-1,0)~h(i-1,k)有关,且如果h(i-1,k)=true,必然有h(i,k)=true,h(i,k)的值存在继承性,而程序结束时,我们也只关心h(n,k),因此,我们可以用一维数组h(k)来存储中间信息。
为了避免重复计算,可以让k从大到小变化,为了避免出现负数,k的变化范围为v~volume[i].示例程序:#include<iostream>#include<cstring>using namespace std;int v,n;int volume[31];//存储n件物品的体积int h[20001];//h[i]=1,表示n件物品通过某种组合,所构成的体积和正和等于i;//h[i]=0,表示n件物品无论如何组合,体积和都无法等于iint main(){freopen(\"in.txt\",\"r\",stdin);freopen(\"out.txt\",\"w\",stdout);int v,n,i,j,k;while(cin>>v>>n){for(i=1;i<=n;i++)cin>>volume[i];memset(h,0,sizeof(h));h[0]=1;for(i=1;i<=n;i++)for(k=v;k>=volume[i];k--)h[k]=h[k]||h[k-volume[i]];[Page]j=v;while(j>0&&h[j]==0)j--;cout<<v-j<<endl;}return 0;。
c装箱和拆箱定义
c装箱和拆箱定义【C装箱和拆箱】C语言中的装箱和拆箱是指将不同数据类型之间进行转换的操作。
在编程中,有时候我们需要将一个数据从一种类型转换为另一种类型,这就需要用到装箱和拆箱操作。
让我们来看看装箱操作。
装箱是将一个基本数据类型转换为一个对象类型的过程。
这样做的好处是可以方便地将数据传递给需要对象类型参数的函数或方法。
举个例子,如果我们有一个整数变量int num,但是我们需要将它传递给一个接受对象类型参数的函数,这时就需要将num进行装箱操作,转换为一个对象类型的Integer对象。
装箱操作通常是隐式的,编译器会自动帮我们完成这个转换。
但是有时候我们也可以显式地进行装箱操作,使用包装类的构造函数或者valueOf方法。
比如,我们可以将int类型的数据装箱为Integer 对象:Integer num = new Integer(5) 或者Integer num = Integer.valueOf(5)。
接下来,让我们来看看拆箱操作。
拆箱是将一个对象类型转换为一个基本数据类型的过程。
这样做的好处是可以方便地将对象类型的数据转换为基本数据类型,方便进行计算或其他操作。
举个例子,如果我们有一个Integer对象num,但是我们需要将它转换为int类型进行计算,这时就需要进行拆箱操作。
拆箱操作也可以是隐式的,编译器会自动帮我们完成这个转换。
但是有时候我们也可以显式地进行拆箱操作,使用包装类的intValue、doubleValue等方法。
比如,我们可以将Integer对象转换为int类型:int num = num.intValue()。
在实际编程中,装箱和拆箱操作是非常常见的。
但是需要注意的是,装箱和拆箱操作会消耗一定的系统资源,所以在性能要求较高的情况下,应该尽量减少装箱和拆箱的次数,避免影响程序的性能。
总的来说,装箱和拆箱是在不同数据类型之间进行转换的操作,可以方便地在不同类型之间传递数据或进行计算。
装箱问题C语言实现(算法分析)
算法分析题目:装箱(Bin Packing)问题院别:数学与计算科学学院专业:信息与计算科学*名:***学号:********** 指导老师:***日期: 2011. 06. 9目录一、问题描述 (1)二、问题分析 (1)三、代码实现 (2)四、测试结果 (3)五、心得体会 (4)六、源程序 (4)一、问题描述一个工厂制造的产品形状都是长方体,它们的高度都是h,长和宽都相等,一共有六个型号,他们的长宽分别为1*1, 2*2, 3*3, 4*4, 5*5,6*6.这些产品通常使用一个 6*6*h 的长方体包裹包装然后邮寄给客户。
因为邮费很贵,所以工厂要想方设法的减小每个订单运送时的包裹数量。
他们很需要有一个好的程序帮他们解决这个问题从而节省费用。
二、问题分析对于6*6的一个箱子来说,最多只能放一个6*6或一个5*5或4*4的盒子,所以我们初始化需要的箱子数时就是这这几种箱子的个数和,对于3*3的箱子来说,我们可以放一个或2个或3个或4个,这我们可以通过整除和取模来确定放了3*3盒子的箱子数,再把它加入到总箱子数中,接下来我们就是把1*1和 2*2的盒子塞进前面所需的箱子中,当塞不完时再来新增盒子,我们首先要将前面的箱子剩余的空间统计出来,并且要以2*2的优先考虑,因为我们可以把多余的2*2的位置变为填充4个1*1的,毕竟1*1的只要有空间随处都可以塞。
所以当我们的箱子要是装了1个5*5的盒子的话,那么它就只能塞1*1的了,一个可以塞11个1*1的,对于装了4*4的盒子的话,那么还可以装5个2*2的盒子,暂且不要去转话成1*1的,除非没办法只能装1*1的,对于3*3 的话就可以根据取模之后一个箱子剩下的空间了,如果一个箱子中只放了一个3*3的,那么还剩下3个3*3的空间可以放,我们知道可以放5个2*2的和7个 1*1的,对于放了2个3*3的箱子,我们剩下的空间可以放3个2*2的以及6个1*1的,对于放了3个3*3的箱子,我们只能放1个2*2的和5个 1*1的,这样一来我们就统计出了此时可以放2*2以及1*1的空间到底有多少,接下来我们就放箱子进去,放一个就减一个,直到1*1的和2*2的为0。
三维装箱问题的算法
三维装箱问题的算法
三维装箱问题是一种经典的组合优化问题,它要求将一组物品(物品的尺寸由长、宽、高表示)装入一些箱子(箱子的尺寸也由长、宽、高表示),使得物品能够尽可能紧密地装入箱子中,并且所需要的箱子数量要尽量少。
下面是一个基于贪心算法的解决方案:
步骤1:将所有物品按照体积从大到小进行排序。
步骤2:创建一个空的箱子列表,将第一个物品放入第一个箱子。
步骤3:遍历剩下的物品,按照如下的方式尝试将每个物品放
入已有的箱子中:
- 对于每个箱子,计算将该物品放入箱子后箱子的剩余容量。
- 如果该剩余容量大于等于该物品的体积,则将该物品放入
该箱子中,并更新箱子的剩余容量。
- 如果该物品无法放入任何已有的箱子中,则将该物品放入
一个新的箱子,并加入到箱子列表中。
步骤4:重复步骤3,直到将所有物品放入箱子中。
这个贪心算法的思想是每次选择最大的物品尝试放入已有的箱
子中,以便尽可能地利用空间。
但是,这个算法并不能保证得到最优解,因为在选择某个物品放入箱子时,并没有考虑到后续物品的放置情况。
解决三维装箱问题的最优算法是NP-hard问题,可以采用启发
式算法或者近似算法来求解,例如基于遗传算法、模拟退火算法、禁忌搜索等。
这些算法的思想是通过搜索空间的不同方案,寻求某一个局部最优解或者近似最优解。
具体选择哪种算法需要根据实际问题的规模和要求进行评估。
c装箱和拆箱定义
c装箱和拆箱定义
装箱和拆箱是我们在日常生活中常常会遇到的操作,无论是在搬家、旅行或者收纳物品时,都会涉及到这两个过程。
装箱就是将物品整齐地放入箱子或容器中,以便搬运或储存。
而拆箱则是将箱子中的物品取出,进行整理或使用。
这两个过程看似简单,实际上却需要一定的技巧和耐心。
装箱是一个重要的技能,通过合理的规划和安排,可以最大限度地利用箱子的空间,确保物品不受损坏。
首先,我们需要选择合适的箱子,根据物品的种类和数量来选择大小和材质。
然后,可以先将大件物品放入箱子中,再根据大小和重量适当地填充一些衣物或软垫,以防止物品在运输过程中摩擦或碰撞。
另外,对于易碎品或贵重物品,可以用泡沫或气泡膜进行包裹,以增加保护。
在装箱的过程中,需要注意将重的物品放在底部,轻的物品放在顶部,以保持箱子的平衡。
同时,可以在箱子内部放置隔板或隔间,将物品分类存放,便于取出和整理。
此外,可以在箱子外部标注清晰的标签,标明箱子内的物品种类和数量,方便日后查找和使用。
拆箱的过程与装箱相反,同样需要耐心和细心。
首先,需要小心地打开箱子,避免在拆箱过程中损坏箱子或物品。
然后,可以根据标签逐一取出物品,按照分类整理或使用。
在拆箱的过程中,也可以顺便清理箱子内部的灰尘或异物,以便下次再次使用。
装箱和拆箱虽然是简单的日常操作,但却能体现一个人的细致和耐心。
通过合理的规划和整理,可以有效地提高物品的利用率,减少损坏的可能性。
因此,在进行装箱和拆箱的过程中,不妨尝试一些新的方法和技巧,提升自己的生活品质。
愿每一个箱子的装满都是幸福,每一个箱子的打开都是惊喜。
C语言基于贪心算法解决装箱问题的方法
C语⾔基于贪⼼算法解决装箱问题的⽅法本⽂实例讲述了C语⾔基于贪⼼算法解决装箱问题的⽅法。
分享给⼤家供⼤家参考,具体如下:问题描述:有⼀些箱⼦,容量为V,同时有n个物品,每个物品有⼀个体积(⼩于等于箱⼦容量),要求将物品全部装⼊箱⼦中,使占⽤的箱⼦数尽量少。
贪⼼算法中要求每⼀步的解都是当前步骤中的最优解。
原问题的解可以通过⼀系列局部最优的选择来达到,这种选择并不依赖于⼦问题的解。
算法思想:1、数据结构要求求解箱⼦数⽬,也就是说不能确定会占⽤多少个箱⼦,因此采⽤链表的形式来存储箱⼦及其信息。
同时,每个箱⼦中物品的数⽬也⽆法确定,同理采⽤链表来存储每个箱⼦中的物品信息。
由此得出数据节点的定义:typedef struct{int gno;int gv;}Goods;typedef struct node{int gno;struct node *link;}GNode;typedef struct node1{int remainder;GNode * head;struct node1 * next;}GBox;2、求解思路使打开的箱⼦数尽量少,也就是说每个箱⼦容积被尽可能多地占⽤。
将物品按照体积降序排列后,再从第⼀个物品开始,挨个寻找能放下它的箱⼦,这样可以保证局部最优。
void GoodsSort(Goods goods[], int n){int i, j;Goods t;for (i = 0; i<n - 1; i++){for (j = i + 1; j<n; j++){if (goods[i].gv<goods[j].gv){t = goods[i];goods[i] = goods[j];goods[j] = t;}}}for (i = 0; i<n; i++)printf("%d %d\n", goods[i].gno, goods[i].gv);排序完成,就可以正式开始装箱⼦了。
C语言实现简单推箱子游戏
C语⾔实现简单推箱⼦游戏使⽤C语⾔实现超简单的推箱⼦游戏,供⼤家参考,具体内容如下感谢您打开了这篇⽂章,下⾯我将讲述⼀下推箱⼦是如何实现的。
另外附赠适配该程序简单好⽤专属推箱⼦地图编辑器让您在16 * 16⼤地图的条件下也能轻松编辑地图。
链接:本程序在没有检测到地图⽂件的情况下也能独⾃运⾏!代码中储存了推箱⼦游戏第⼀关的标准地图,让您在没有地图⽂件的情况下也能熟悉整个程序的流程!当然,拥有地图⽂件会也会获得更好的游戏体验,请⾃⾏编辑。
废话不多说!下⾯进⼊技术环节:C语⾔版多功能推箱⼦编译环境: Windows VS2019其他编译器,可通过查看下⽂的“注意事项”将代码更正为其他平台可正常版本需求:控制⼈物将箱⼦推⾄⽬标中,⽬标全部完成进⼊下⼀关。
思路:使⽤⼆维数组储存不同数字,数字包括了地图中所有的元素,通过按键控制⼈物完成推箱⼦的操作,达成关卡内的所有⽬标后,⾃动进⼊下⼀关。
做法:主要逻辑移动推箱⼦部分:按下⽅向键后,双重循环找到⼈物,根据移动⽅向储存⼈物、⼈物前⾯、箱⼦、箱⼦前⾯四⼤基础信息,并通过判断前⽅数组值是否是墙壁、⽬标等,进⾏⼈物移动和箱⼦移动操作。
具体详细做法我已经整理到了代码注释当中,以便⼀⼀对应查看。
使⽤到知识点:循环、⼆维数组、读取⽂件难点:在⼈物和箱⼦移动的同时,有需要注意当⼈物移动到了未完成⽬标或已完成⽬标、箱⼦移动到了已完成⽬标的情况,这种情况需要判断在⼈物/箱⼦离开之后,原地⼜再次变为原元素。
说明:程序前部分有较多代码⽤于写出未检测到⽂件的情况逻辑和关卡选择逻辑,如果要直接查看核⼼代码请移动到operation();操作⼈物函数和gbszszhs(char ch);修改⼆维数组函数。
注意:由于编译器原因,程序中_kbhit()和_getch()函数可能在其他编译器上编译会出现错误,解决办法是去掉函数前⾯的“_”。
同时,要将⽂件打开函数fopen_s(&fp, FLPA, “r”);更改为fp = fopen(FLPA, “r”);fcanf_s更改为fcanf scanf_s()更改为scanf运⾏效果:菜单选择:游戏进⾏:代码实现:#include <stdio.h>#include <windows.h>#include <conio.h>//0代表空地,1代表墙,2代表未达成的⽬标,3代表箱⼦,4代表玩家,5代表已放箱⼦的⽬标,//6代表⼈暂时所在的未达成的⽬标,7代表⼈暂时所在的已达成的⽬标,8代表箱⼦暂时所在的已达成的⽬标#define WH 16 //地图的宽⾼#define BYT 529 //⼀关需要跳过的字数因为⽂件指针定位函数的原因,有时定位可能会不准确,可以通过修改BYT进⾏适配#define FLPA "C:\\Users\\ASUS\\Desktop\\推箱⼦地图.txt" //需要读取地图⽂件的路径游戏之前需进⾏设置!!//找不到路径将只能进⾏第⼀关游戏//注意:游戏地图边界不可以当做墙壁使⽤!#define INITMAP \int mapch_init[WH][WH] = { \{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \{0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, \{0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0}, \{0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0}, \{0, 0, 0, 0, 1, 1, 1, 3, 0, 3, 2, 1, 0, 0, 0, 0}, \{0, 0, 0, 0, 1, 2, 0, 3, 4, 1, 1, 1, 0, 0, 0, 0}, \{0, 0, 0, 0, 1, 1, 1, 1, 3, 1, 0, 0, 0, 0, 0, 0}, \{0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0}, \{0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, \{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \};int mapch[WH][WH];//所有函数之间不是独⽴和顺序的,会互相调⽤void HideCursor(); //隐藏光标void gotoxy(int x, int y);//光标定位void scmbxyhs(); //输出地图下⽅⽂字信息函数void wjzdwjzjjrqk(); //未找到⽂件直接进⼊第⼀关情况int gkxzhs(); //关卡选择函数void cwjzjrwkdhs(); //从⽂件中进⼊关卡的函数void gnxzjm(); //主菜单选择void cshhs(); //初始化函数void tranmap(); //翻译并画出地图void detection(); //寻找所有该地图中未完成的⽬标void gktgszxhs(); //判断关卡是否通过,是进⾏下⼀关卡void operation(); //操作⼈物主要函数***void gbszszhs(char ch); //改变数组数值函数int updatetime(); //获取⼀次电脑现在的时间void process(); //主要流程int main(){cshhs(); //初始化函数process(); //主要流程return 0;}//游戏开始初始化部分void scmbxyhs() //输出地图提⽰信息函数{gotoxy(34, 17);printf("本关剩余⽬标数:");gotoxy(34, 19);printf("本关已⾛步数:");gotoxy(32, 21);printf("您使⽤秒完成了本关!");gotoxy(49, 19);printf("0"); //输出初始的步数0}void wjzdwjzjjrqk() //未找到⽂件直接进⼊第⼀关情况{system("cls");printf("地图⽂件不存在,\n直接进⼊第⼀关");INITMAP //初始地图数组for (int i = 0; i < WH; i ) //如果地图⽂件不存在则将初始地图数组的值赋给需要使⽤的地图for (int j = 0; j < WH; j ) //将初始地图数组的值复制给当前地图数组mapch[i][j] = mapch_init[i][j];Sleep(2000); //等待两秒进⼊第⼀关system("cls"); //清屏tranmap(); //画出初始地图detection(); //⽬标信息scmbxyhs(); //输出地图下⽅⽂字信息}int n = 1; //输⼊关卡变量**int maxn = 0; //最⼤关数int dczdgshs() //最⼤关数{FILE* fp = NULL; //因为⽤于提⽰和限制输⼊情况,所以需要得到最⼤关卡数maxnfopen_s(&fp, FLPA, "r");if (fp == NULL){wjzdwjzjjrqk(); //未找到⽂件直接进⼊第⼀关情况return 0;}int temp = 0; //临时变量⽤来统计地图⽂件全字节数rewind(fp); //⽂件指针移动到⽂件⾸部while (!feof(fp)) //⽂件指针还没有到⽂件尾进⼊循环{fgetc(fp); //读字符函数从⽂件开头读,向后移动⽂件指针temp ; //每读⼀个字符则临时变量⾃增,统计出全⽂件有⼏个字符}fclose(fp); //⽂件使⽤完成关闭⽂件maxn = temp / BYT 1; //最⼤关数就是所有字符的数量除以⼀关的字符数return 1;}int gkxzhs() //选择关卡函数{system("cls"); //输出关卡选择提⽰gotoxy(26, 8);printf("请输⼊想要挑战的关卡:(回车确认)");if (!dczdgshs()) //得出最⼤关数函数,返回值为0代表未找到地图⽂件,直接进⼊流程return 0;gotoxy(36, 10);printf("请输⼊1- %d ", maxn);//输出提⽰最⼤关数信息srgk: //重新选择关卡gotoxy(41, 12);scanf_s("%d", &n);if (n<1 || n>maxn) //对输⼊的错误关卡信息加以限制{gotoxy(36, 12);printf(" ");gotoxy(33, 11);printf("请输⼊正确的关数");goto srgk; //如果输⼊错误的关卡输出提⽰信息并返回到输⼊的地⽅重新输⼊}return 1; //如果找到了⽂件就返回1}void cwjzjrwkdhs() //从⽂件中进⼊关卡,适⽤于可以找到地图⽂件的情况{//关数变量n的默认初始化值为1FILE* fp = NULL;fopen_s(&fp, FLPA, "rb");if (fp == NULL){wjzdwjzjjrqk(); //直接进⼊第⼀关函数return; //地图⽂件不存在则直接进⼊第⼀关}//读⽂件进⼊关卡的代码,从第⼀关进⼊和选择特定关从n关进⼊两种情况都会执⾏//流程如果⽤到该函数,检测已达成的⽬标和未达成⽬标的个数⼀直则调⽤函数,n关数⾃增1 int skip = (n - 1) * BYT; //到n关需要跳过的字数跳过⼀关需要的字数为512fseek(fp, skip, 0); //定位到地图⽂件第skip个字节处开始读取int i, j;for (i = 0; i < WH; i ) //读取512个字符{for (j = 0; j < WH; j ){fscanf_s(fp, "%d ", &mapch[i][j]);//格式读函数,直接以整数格式读取数值存⼊地图数组mapch中printf("%d ", mapch[i][j]);}printf("\n");}fclose(fp); //读取⽂件完毕,将⽂件关闭system("cls");}void gnxzjm() //主菜单页⾯选择{system("cls");gotoxy(39, 8);printf("推箱⼦");gotoxy(34, 10);printf("输⼊1 开始新游戏");gotoxy(34, 12);printf("输⼊2 选择关卡");gotoxy(34, 14);printf("输⼊3 退出游戏");Head: //⽤于返回的标签gotoxy(34, 17);char chn=_getch(); //选择游戏模式if (chn == '3'){system("cls"); //退出游戏则输出提⽰信息gotoxy(34, 12);printf("欢迎下次光临");Sleep(2000);gotoxy(0, 24);exit(0); //退出游戏}else if (chn == '2'){if (!gkxzhs()) //进⼊关卡选择return; //如果关卡选择函数返回值为0则代表未找到⽂件,直接跳出初始化函数//如果返回1找到⽂件则继续执⾏该函数下⾯的内容}else if (chn == '1')n = 1; //如果选择新游戏,直接从第⼀关开始else{gotoxy(34, 16);printf("请输⼊正确的选择:");goto Head; //选择错误的菜单,则重新返回选择菜单的地⽅}//选择1的情况:cwjzjrwkdhs(); //从⽂件读取关卡的函数detection(); //统计当前关卡的⽬标数tranmap(); //画出地图scmbxyhs(); //输出地图下⽅⽂字信息}int detunf;//检测未完成⽬标的变量,初始为⼀个关卡中未完成⽬标的个数,箱⼦碰到未完成⽬标时,⾃减void detection() //检测当前关中有多少个⽬标{//detunfdetunf = 0; //从0开始统计int i, j;for (i = 0; i < WH; i )for (j = 0; j < WH; j )if (mapch[i][j] == 2)detunf ;gotoxy(50,17); //在提⽰信息的位置输出剩余⽬标信息printf("%d", detunf);}void cshhs() //总初始化函数{system("title 推箱⼦");//控制台标题system("mode con cols=84 lines=26");//设置控制台⼤⼩,第⼀个参数为横轴,地图参数32 16gnxzjm(); //主菜单页⾯选择HideCursor(); //隐藏光标函数dczdgshs(); //找到地图⽂件的情况下得出最⼤关数}//游戏流程部分void tranmap() //翻译地图{gotoxy(26, 1); //输出地图时在控制台中间输出,地图最上⽅空⼀⾏int i, j;for (i = 0; i < WH; i ){for (j = 0; j < WH; j ){if (mapch[i][j] == 1)printf("■");else if (mapch[i][j] == 2)printf("★");else if (mapch[i][j] == 3 || mapch[i][j] == 8)printf("●");else if (mapch[i][j] == 4 || mapch[i][j] == 6 || mapch[i][j] == 7)printf("♀");else if (mapch[i][j] == 5)printf("--");elseprintf(" ");}gotoxy(26, i 1); //根据数组的y轴更改地图输出的y轴,地图最上⽅空⼀⾏}}int opnum; //每⼀关⾏⾛的步数int time;int time_2;void gktgszxhs() //判断当前关卡是否通过,是进⼊下⼀关{if (detunf == 0) //当前关卡⽬标为0时{n ; //关卡变量⾃增if (n > maxn) //如果关数n⼤于了最⼤关卡数则返回主菜单{tranmap(); //画出地图gotoxy(26, 22);printf("您已通关所有关卡,3秒后返回主菜单!");Sleep(3000); //等待三秒opnum = 0, time = updatetime(),time_2 = 0;//⾏⾛的步数,本关时间清0,重新获取当前时间,\因为需要输出的time_2是⽤当前时间-刚开始的时间gnxzjm(); //主菜单页⾯选择函数}else{tranmap(); //画出地图Sleep(2000); //等候两秒cwjzjrwkdhs(); //当前关卡⽬标为0时,从⽂件中向地图数组中读⼊下⼀关卡的信息detection(); //统计当前关卡⽬标个数scmbxyhs(); //输出地图下⽅的信息opnum = 0, time = updatetime(),time_2 = 0;//注释见297⾏//按键结束之后操控函数会调⽤画出地图函数}}}int i, j; //找到后的⼈的坐标int box_x, box_y; //箱⼦的坐标int boxnext_x, boxnext_y; //箱⼦前⾯的坐标int peonext_x, peonext_y; //⼈前⾯的坐标void gbszszhs(char ch) //修改地图数组值主要函数**{for (i = 0; i < WH; i ) //遍历 i是y轴,j是x轴{for (j = 0; j < WH; j ){if (mapch[i][j] == 4 || mapch[i][j] == 6 || mapch[i][j] == 7) //找到⼈的位置{if (ch == 'w') // ⽤于确定不同⽅向上箱⼦、箱⼦前⾯、⼈前⾯的坐标{box_y = i - 1; box_x = j; //箱⼦当前boxnext_y = i - 2; boxnext_x = j; //箱⼦前⾯peonext_y = i - 1; peonext_x = j; //⼈前⾯}else if (ch == 'a'){box_y = i; box_x = j - 1;boxnext_y = i; boxnext_x = j - 2;peonext_y = i; peonext_x = j - 1;}else if (ch == 's'){box_y = i 1; box_x = j;boxnext_y = i 2; boxnext_x = j;peonext_y = i 1; peonext_x = j;}else if (ch == 'd'){box_y = i; box_x = j 1;boxnext_y = i; boxnext_x = j 2;peonext_y = i; peonext_x = j 1;}//排除⼤的错误if (mapch[box_y][box_x] == 3 || mapch[box_y][box_x] == 8) //如果⼈的前边是箱⼦if (mapch[boxnext_y][boxnext_x] == 1 || mapch[boxnext_y][boxnext_x] == 3 || mapch[boxnext_y][boxnext_x] == 8) return; //如果箱⼦前边是墙或者是箱⼦直接结束修改函数if (mapch[box_y][box_x] == 1) //⼈的前边不能是墙return; //如果⼈的前边是墙直接结束修改opnum ; //每次有效操作步数⾃增⼀次,并输出gotoxy(49, 19);printf("%d", opnum);//步数//箱⼦改变if (mapch[box_y][box_x] == 3 || mapch[box_y][box_x] == 8) //如果⼈的前边是箱⼦{//箱⼦原地改变:if (mapch[box_y][box_x] == 3) //如果箱⼦所在的位置是⼀般箱⼦mapch[box_y][box_x] = 0; //改变为空地else if (mapch[box_y][box_x] == 8) //如果箱⼦所在的位置是箱⼦暂时所在已达成的⽬标mapch[box_y][box_x] = 5; //改变为已达成的⽬标//箱⼦的下⼀步改变:if (mapch[boxnext_y][boxnext_x] == 2) //如果箱⼦前⾯的格⼦是未放箱⼦的⽬标{mapch[boxnext_y][boxnext_x] = 5; //则该格⼦变为已放箱⼦的⽬标detunf--; //本关⽬标减1gotoxy(50, 17); //输出本关剩余⽬标个数printf("%d", detunf);}else if (mapch[boxnext_y][boxnext_x] == 0) //如果箱⼦前⾯是空地mapch[boxnext_y][boxnext_x] = 3; //则变为普通箱⼦else if (mapch[boxnext_y][boxnext_x] == 5) //如果箱⼦前⾯是已经放过箱⼦的⽬标mapch[boxnext_y][boxnext_x] = 8; //则变为箱⼦暂时所在已达成的⽬标}//原地改变if (mapch[i][j] == 6)mapch[i][j] = 2; //⾛出去之后原地⼜变回2 未达成的⽬标else if (mapch[i][j] == 7)mapch[i][j] = 5; //⾛出去之后原地⼜变回5 已达成的⽬标else if (mapch[i][j] == 4)mapch[i][j] = 0; //⾛出去之后原地变回4 ⼈的原型//⼈下⼀步改变if (mapch[peonext_y][peonext_x] == 0 || mapch[peonext_y][peonext_y] == 3)//如果他的下⼀步是普通箱⼦或者空地 mapch[peonext_y][peonext_x] = 4; //⼈是普通的⼈if (mapch[peonext_y][peonext_x] == 2) //如果他的下⼀步还是未达成的⽬标mapch[peonext_y][peonext_x] = 6; //⼈是⼈暂时所在未达成的⽬标if (mapch[peonext_y][peonext_x] == 5) //如果⼈的下⼀步是已经达成的⽬标mapch[peonext_y][peonext_x] = 7; //⼈是⼈暂时所在已经达成的⽬标if (mapch[peonext_y][peonext_x] == 8) //如果⼈的下⼀步是箱⼦暂时所在已达成的⽬标mapch[peonext_y][peonext_x] = 7; //⼈还是暂时所在已达成的⽬标goto L1; //修改完成后不需要遍历后⾯的数组,直接跳出所有循环}}}L1: //⽤于跳出的标签gktgszxhs(); //关卡通过则进⼊下⼀关}void operation() //操作⼈物函数{char ch = _getch(); //接收输⼊的⽅向 _getch()即使接收switch (ch){case 'w': //向不同⽅向移动gbszszhs(ch); //传递参数,修改⼆维数组break;case 'a':gbszszhs(ch);break;case 's':gbszszhs(ch);break;case 'd':gbszszhs(ch);break;}tranmap(); //重新画出地图}int updatetime() //获取⼀次电脑现在的时间{int now;SYSTEMTIME system_time;GetLocalTime(&system_time);now = system_time.wMinute * 60 system_time.wSecond;return now;}void process() //主要流程{time = updatetime(); //初始时间while (1){time_2 = updatetime() - time; //每关的时间time_2,值为当前时间减去当前关卡开始的时间gotoxy(39, 21);printf("%d s", time_2); //输出if(_kbhit())operation(); //操作⼈物、修改数值主要函数Sleep(20); //游戏帧率和⼿感休眠时间}}void gotoxy(int x, int y) //光标定位{COORD pos = { x,y };SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);}void HideCursor() //光标隐藏{CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);}主要函数:gbszszhs()⾥⾯的逻辑是⽐较复杂的,我当时写这段代码的时候也是反反复复修改好多次甚⾄推翻重做才理通顺这些逻辑的。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
算法分析题目:装箱(Bin Packing)问题院别:数学与计算科学学院专业:信息与计算科学*名:***学号:********** 指导老师:***日期: 2011. 06. 9目录一、问题描述 (1)二、问题分析 (1)三、代码实现 (2)四、测试结果 (3)五、心得体会 (4)六、源程序 (4)一、问题描述一个工厂制造的产品形状都是长方体,它们的高度都是h,长和宽都相等,一共有六个型号,他们的长宽分别为1*1, 2*2, 3*3, 4*4, 5*5,6*6.这些产品通常使用一个 6*6*h 的长方体包裹包装然后邮寄给客户。
因为邮费很贵,所以工厂要想方设法的减小每个订单运送时的包裹数量。
他们很需要有一个好的程序帮他们解决这个问题从而节省费用。
二、问题分析对于6*6的一个箱子来说,最多只能放一个6*6或一个5*5或4*4的盒子,所以我们初始化需要的箱子数时就是这这几种箱子的个数和,对于3*3的箱子来说,我们可以放一个或2个或3个或4个,这我们可以通过整除和取模来确定放了3*3盒子的箱子数,再把它加入到总箱子数中,接下来我们就是把1*1和 2*2的盒子塞进前面所需的箱子中,当塞不完时再来新增盒子,我们首先要将前面的箱子剩余的空间统计出来,并且要以2*2的优先考虑,因为我们可以把多余的2*2的位置变为填充4个1*1的,毕竟1*1的只要有空间随处都可以塞。
所以当我们的箱子要是装了1个5*5的盒子的话,那么它就只能塞1*1的了,一个可以塞11个1*1的,对于装了4*4的盒子的话,那么还可以装5个2*2的盒子,暂且不要去转话成1*1的,除非没办法只能装1*1的,对于3*3 的话就可以根据取模之后一个箱子剩下的空间了,如果一个箱子中只放了一个3*3的,那么还剩下3个3*3的空间可以放,我们知道可以放5个2*2的和7个 1*1的,对于放了2个3*3的箱子,我们剩下的空间可以放3个2*2的以及6个1*1的,对于放了3个3*3的箱子,我们只能放1个2*2的和5个 1*1的,这样一来我们就统计出了此时可以放2*2以及1*1的空间到底有多少,接下来我们就放箱子进去,放一个就减一个,直到1*1的和2*2的为0。
三、代码实现(C语言)C语言代码主要有三部分组成,main()函数、Input()和Output()。
Input()函数主要接收键盘输入的值(各型号产品的数量),将其存入数组product[n]中。
Output()对各种类型的产品进行逻辑判断,优先让型号为6*6、5*5、4*4、3*3的产品装入箱子,然后再将型号为2*2、1*1的产品插入之前装的箱子2*2的先插入,之后插入1*1的,如果都插满了还有1*1或2*2的产品,就在新开箱子将其装入,直到所有的产品都被装入箱子。
最后打印输出每个箱子具体装入产品及型号的情况和总共用的箱子数。
四、测试结果五、心得体会时间飞逝,转眼间一个学期又过去了,在上算法分析理论课的过程中,我对很多经典的算法有了更深层次的了解。
解决同一个问题有很多不同的算法,所以在选择算法的过程中要考虑很多因素,一点小小的改进程序执行的时间可能就会缩短好几倍,算法的效率成了评价一个算法好坏的不可或缺的一个标准。
这次课设,我选择了装箱(Bin Packing)问题,在实例化题目和设计算法的过程中,我查阅了很多相关的资料,在此我也学到了很多有关算法设计方面的知识,程序的编写和调试也花了我很多时间,最终通过自己的努力完成了课程设计。
在此,我要感谢课设的指导老师!六、源程序#include<stdio.h>#define BOX_VAL 36#define N 6int product[N]; //存放各种类型的产品数量int boxNum = 0; //存放订单需要的箱子数目void Input();void Output();void main(){Input();Output();printf("该订单需要的箱子数目为:%d\n",boxNum);printf("\n");}//用来输入每种产品的数量,保存在product[N]数组中void Input(){int i;printf("Please input products information!\n");for(i=0;i<N;i++){printf(" %d*%d style of products is: ",i+1,i+1);scanf("%d",&product[i]);printf("\n");}}//处理产品具体的装箱过程和输出装箱结果void Output(){int temp = 0;int pro1 = product[0];int pro2 = product[1];if(product[5]>0){boxNum += product[5];printf("装型号为6*6产品的箱子数为:%d\n",product[5]);printf("\n");}if(product[4]>0){boxNum += product[4];if((pro1-product[4]*11)>=0){printf("装型号为5*5和1*1产品的箱子数为:%d\n",product[4]);printf("\n");pro1 -= product[4]*11;}else{if(pro1%11==0){printf("装型号为5*5和1*1产品的箱子数为:%d\n",pro1/11);printf("\n");pro1 = 0;}else{printf("装型号为5*5和1*1产品的箱子数为:%d\n",(pro1/11)+1); printf("\n");printf("只装型号为5*5产品的箱子数为:%d\n",(product[4]-(pro1/11)-1));printf("\n");pro1 = 0;}}}if(product[3]>0){boxNum += product[3];if((pro2-product[3]*5)>=0){printf("装型号为4*4和2*2产品的箱子数为:%d\n",product[3]);printf("\n");pro2 -= product[3]*5;}else{if(pro2%5==0){printf("装型号为4*4和2*2产品的箱子数为:%d\n",pro2/5);printf("\n");pro2 = 0;}else{printf("装型号为4*4和2*2产品的箱子数为:%d\n",(pro2/5)+1);printf("\n");printf("只装型号为4*4产品的箱子数为:%d\n",(product[3]-(pro2/5)-1));printf("\n");pro2 = 0;}}}if(product[2]>0){if(product[2]%4==0){boxNum += product[2]/4;printf("只装型号为3*3产品的箱子数为:%d\n",product[2]/4);printf("\n");}else{int temp = 0;boxNum += product[2]/4 + 1;printf("只装型号为3*3产品的箱子数为:%d\n",product[2]/4);printf("\n");temp = product[2]%4;switch(temp){case 1:if(pro2>=6){pro2 = pro2 - 6;printf("装型号为3*3、2*2产品的箱子数为:%d\n",1);printf("\n");}else{pro1 = 27 - pro2*4;pro2 = 0;if(pro1<=0){printf("装型号为3*3、2*2、1*1产品的箱子数为:%d\n",1);printf("\n");pro1 = 0;}}break;case 2:if(pro2>=4){pro2 = pro2 - 4;printf("装型号为3*3、2*2产品的箱子数为:%d\n",1);printf("\n");}else{pro1 = 18 - pro2*4;pro2 = 0;if(pro1<=0){printf("装型号为3*3、2*2、1*1产品的箱子数为:%d\n",1);printf("\n");pro1 = 0;}}break;case 3:if(pro2>=2){pro2 = pro2 - 2;printf("装型号为3*3、2*2产品的箱子数为:%d\n",1);printf("\n");}else{pro1 = 9 - pro2*4;pro2 = 0;if(pro1<=0){printf("装型号为3*3、2*2、1*1产品的箱子数为:%d\n",1);printf("\n");pro1 = 0;}}break;}}}if(pro2>0){if(pro2%9==0){boxNum += pro2/9;printf("只装型号为2*2产品的箱子数为:%d\n",pro2/9);printf("\n");pro2 = 0;if(pro1%36==0){boxNum += pro1/36;printf("只装型号为1*1产品的箱子数为:%d\n",pro1/36);printf("\n");pro1 = 0;}else{boxNum += pro1/36 + 1;printf("只装型号为1*1产品的箱子数为:%d\n",pro1/36+1);printf("\n");pro1 = 0;}}else{if((pro2*4 + pro1)%36==0){boxNum += (pro2*4 + pro1)/36;printf("装型号为2*2、1*1产品的箱子数为:%d\n",(pro2*4 + pro1)/36);printf("\n");}else{boxNum += (pro2*4 + pro1)/36 + 1;printf("装型号为2*2、1*1产品的箱子数为:%d\n",(pro2*4 + pro1)/36+1);printf("\n");}}}}。