网格背包的简单实现

如果是使用网格背包实现的的背包界面,类似于《暗黑》这种背包,我是这么来定义结构的。发现和原来做的一个开纸的算法很类似,但是恰好反过来。反正没事儿想起来实现一下也不错。

一个物品的占位,默认左上角为(0,0)点。策划在填表的时候,只需要根据对角线关系填写(1,1)这个点就可以了。

服务器Item对象,仅需要存储左上角(0,0)点所在的二维数组的位置即可,如果考虑到物品的旋转(行列互换)可以再加入一个值做判断.(感觉实际一般都不能旋转,因为美术做图案的时候也很难保证旋转之后的美观性)

class Item{public:        int uid;      //唯一ID    int quality;  //品质        int pos[2];   //位于背包位置(左上角)       int isRota;   //是否旋转};

这样可以很方便的存储到一个map里面或者vector里面。

那么唯一的问题就是自动整理背包了!我是这么来排布背包的

每次放入背包一个物品,会将背包切割成两个区域,横向一个,下方一个,如果另起一行则会切割出来三个区域。占用一个格子的道具和物品,无论背包怎么整理这些物品都是能够放的下的。因为总的格子数是固定的。所以这些可以最后再填入。暂时不做考虑。

假设:存在n个不同品质的物品,占用标准如下,不考虑旋转,且保证背包(MAX_WIDTH,MAX_HEIGHT)能够放下,放不下舍弃。那么背包应该如何整理(不考虑旋转)。

输入:n个物品,数据结构如上

输出:n个物品,在背包内的位置信息,放不下的默认位置为(0,0)

算法描述,先横向放置,直到放置不下再换行放置。由于高度一致,从宽度大的往小的放,为了保证每一行都放满

根据MAX_WIDTH的奇偶性,分奇数先放还是偶数先放。

补充:为了保证新获得物品可以快速的放入到背包当中,其实可以存储一下int rightPos[2],int bottoPos[2]这两个的位置信息。由于实际情况存在占用一个格子物品的情况。为了防止对算法的影响。占用单个格子的物品,默认从背包底行进行放置如果底行占满则从右列开始进行放置。

   1: #include "stdafx.h"
   2: #include <map>
   3: #include <vector>
   4: #define MAX_WIDTH  100
   5: #define MAX_HEIGHT 100
   6: const int INITPOS_0[2] = { 0, 0 };
   7: const int INITPOS_1[2] = { 2, 0 };
   8: const int INITPOS_2[2] = { 2, 1 };
   9: const int INITPOS_3[2] = { 2, 2 };
  10:  
  11:  
  12: class Item;
  13: typedef std::map<int, Item*> ITEM_MAP;
  14: typedef std::map<int, Item*>::iterator  ITEM_ITERTOR_MAP;
  15:  
  16: class Item
  17: {
  18: public:
  19:     int uid;
  20:     int quality;
  21:     int pos[2];
  22:     int init[2]; //占用位置
  23:  
  24:     Item(int uid_val, int quality_val, const int pos_val[2], const int init_val[2])
  25:     {
  26:         uid = uid_val;
  27:         quality = quality_val;
  28:         memcpy(pos, pos_val, sizeof(pos));
  29:         memcpy(init, init_val, sizeof(init));
  30:     }
  31: };
  32:  
  33: void sort(ITEM_MAP itemMap)
  34: {
  35:     int rightPos[2] = { 0 }; //记录右侧剩余位置的起始
  36:     int bottoPos[2] = { 0 }; //记录底部剩余位置的起始
  37:     std::vector<Item*>    initPos1Vec;//INITPOS_1 一组
  38:     std::vector<Item*>  initPos2Vec;//INITPOS_2 一组
  39:     std::vector<Item*>  initPos3Vec;//INITPOS_3 一组
  40:     for (ITEM_ITERTOR_MAP itor = itemMap.begin(); itor != itemMap.end(); itor++)
  41:     {
  42:         Item* item = itor->second;
  43:         if (item->init[1] == 0)
  44:         {
  45:             initPos1Vec.push_back(item);
  46:         }
  47:         else if (item->init[1] == 1)
  48:         {
  49:             initPos2Vec.push_back(item);
  50:         }
  51:         else if (item->init[1] == 2)
  52:         {
  53:             initPos3Vec.push_back(item);
  54:         }
  55:     }
  56:     if (MAX_WIDTH % 2)
  57:     {//奇数先放 
  58:         //自己实现咯,保密
  59:     }
  60:     else
  61:     {//偶数先放
  62:         //自己实现咯,保密
  63:     }
  64:     return;
  65: }
  66:  
  67: void output(ITEM_MAP itemMap)
  68: {
  69:     for (ITEM_ITERTOR_MAP itor = itemMap.begin(); itor != itemMap.end(); itor++)
  70:     {
  71:         Item* item = itor->second;
  72:         if (item->uid < 10)
  73:         {
  74:             printf("uid:0%d,quality:%d,pos:[%d,%d],init:[%d,%d] \n", item->uid, item->quality, item->pos[0], item->pos[1], item->init[0], item->init[1]);
  75:             continue;
  76:         }
  77:         printf("uid:%d,quality:%d,pos:[%d,%d],init:[%d,%d] \n", item->uid, item->quality, item->pos[0], item->pos[1], item->init[0], item->init[1]);
  78:     }
  79: }
  80:  
  81: int _tmain(int argc, _TCHAR* argv[])
  82: {
  83:     ITEM_MAP itemmap;
  84:     for (int i = 0; i < 15; i++)
  85:     {
  86:         if (i < 5)
  87:         {
  88:             itemmap.insert(ITEM_ITERTOR_MAP::value_type(i + 1, new Item(i + 1, rand() % 3 + 1, INITPOS_0, INITPOS_1)));
  89:             continue;
  90:         }
  91:         if (i < 10)
  92:         {
  93:             itemmap.insert(ITEM_ITERTOR_MAP::value_type(i + 1, new Item(i + 1, rand() % 3 + 1, INITPOS_0, INITPOS_2)));
  94:             continue;
  95:         }
  96:         if (i < 15)
  97:         {
  98:             itemmap.insert(ITEM_ITERTOR_MAP::value_type(i, new Item(i, rand() % 3 + 1, INITPOS_0, INITPOS_3)));
  99:         }
 100:     }
 101:     sort(itemmap);
 102:     output(itemmap);
 103:     getchar();
 104:     return 0;
 105: }
 106:  

时间: 2024-07-31 14:23:26

网格背包的简单实现的相关文章

UVA 562 Dividing coins 分硬币(01背包,简单变形)

题意:一袋硬币两人分,要么公平分,要么不公平,如果能公平分,输出0,否则输出分成两半的最小差距. 思路:将提供的整袋钱的总价取一半来进行01背包,如果能分出出来,就是最佳分法.否则背包容量为一半总价的包能装下的硬币总值就是其中一个人能分得的最多的钱了,总余下的钱减去这包硬币总值.(只需要稍微考虑一下总值是奇数/偶数的问题) 1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #includ

ZOJ 3201 树形dp+背包(简单题)

#include<cstdio> #include<vector> #include<cstring> #include<iostream> using namespace std; const int MAXN = 110; vector<int>a[MAXN]; int n,m,v[MAXN],vis[MAXN],dp[MAXN][MAXN]; void dfs(int root) { dp[root][1] = v[root]; vis[r

【HDU2546】饭卡(01背包应用)

饭卡 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 15779    Accepted Submission(s): 5466 Problem Description 电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额.如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无

HDU 1059 Dividing 分配(AC代码)多重背包的变形

1 #include <iostream> 2 using namespace std; 3 int num[6]; 4 int dp[200]; 5 bool divide(int sum) 6 { 7 int k,i,j; 8 for(i=0;i<6;i++) 9 for(k=0;k<num[i];k++) 10 for(j=sum;j>i;j--) 11 if(dp[j-(i+1)]+(i+1)>dp[j]) 12 dp[j]=dp[j-(i+1)]+(i+1);

游戏服务器背包设计与实现

在游戏开发中,背包是一个非常重要的功能.几乎每个复杂点的游戏都会有背包的功能.不管是手游戏还是网页游戏,不管是SLG游戏,还是ARPG游戏,背包是必不可少的.背包的功能根据策划的要求,有的简单,有的复杂.以下我们就讨论一下几种游戏服务器背包的实现. 1,简单的游戏背包设计 简单的游戏背包到底简单到什么程度呢?那么这个游戏背包只是用来存放物品,不需要记录物品在背包中的位置,只需要记录物品的id和物品的数量即可.这样的游戏背包设计起来非常方便,在数据库中一个物品占一行即可,例如: 当获得物品的时候,

Lightoj 1231 - Coin Change (I) (裸裸的多重背包)

题目链接: Lightoj  1231 - Coin Change (I) 题目描述: 就是有n种硬币,每种硬币有两个属性(价值,数目).问用给定的硬币组成K面值,有多少种方案? 解题思路: 赤果果的多重背包,简单搞一下就好了.席八!烦烦烦.今天绝对是出门刷提前没看黄历,刚开始套了一个多重背包板子,蓝而跑出来的答案并不对,改来改去就错在细节的地方. 1 #include <cmath> 2 #include <cstdio> 3 #include <cstring> 4

背包九讲(转载)

转载 背包问题 //0 1背包 #include<iostream> #include<stdio.h> #include<string.h> using namespace std; int main() { int i,j,n,v,f[1100],w[1100],p[1100]; scanf("%d",&t); while(t--) { memset(f,0,sizeof(f)); scanf("%d%d",&

转:关于垂直网格与CSS基线对其的探讨

网页设计布局中一直比较流行网格对齐,但只是针对水平的对齐,很少或者没有涉及垂直对齐,这篇文章很详细的讲解了垂直网格,乃至基线对其的相关,而css3中的多列布局的也使其显得更为重要,因此还是很有必要去了解学习,至少也是一种思路. 这或许是因为缺少基线网格的理解和欣赏,更或者是因为基线网格是出了名的难以实现, 迄今为止还没有人拿着蓝图让它成功实现. 有些人甚至认为基线在网络上是多余的,基线作为一种排版术语和网络上的行为,在网络上遵循的规则有别于用于印刷的,line-height和真正的行距之间令人沮

创建响应式布局的优秀网格工具集锦《系列四》

如果网页设计和开人员采用了正确的工具集,并基于一个灵活的网格架构,以及能够把响应图像应用到到设计之中,那么创建一个具备响应式的网站并不一定是一项艰巨的任务.在这篇文章中,我们为您呈现了一组优秀的网格工具清单.如果我们错过了任何没有列出在这个清单上的东西,请分享给我们. 您可能感兴趣的相关文章 Web 前端开发人员和设计师必读文章集锦 十个拥有丰富 UI 组件的 JavaScript 框架 十款精心挑选的在线 CSS3 代码生成工具 开发者必备的八个最佳云端集成开发环境 2012年度最佳 Web