解题报告 之 POJ2782 Bin Packing

解题报告 之 POJ2782 Bin Packing

Description

A set of n 1-dimensional items have to be packed in identical bins. All bins have exactly the same length l and each item i has length li<=l . We look for a minimal number of bins q such that 
  • each bin contains at most 2 items, 
  • each item is packed in one of the q bins, 
  • the sum of the lengths of the items packed in a bin does not exceed l .

You are requested, given the integer values n , l , l1 , ..., ln , to compute the optimal number of bins q . 

Input

The first line of the input contains the number of items n (1<=n<=10  5) . The second line contains one integer that corresponds to the bin length l<=10000 . We then have n lines containing one integer value that represents the length of the items.

Output

Your program has to write the minimal number of bins required to pack all items.

Sample Input

10
80
70
15
30
35
10
80
20
35
10
30

Sample Output

6

 ---------------------------------------------------------------------

 话说这是这个博客上写的第一篇博文,其目的很单纯也很神圣,就是和别人约定好了一周不写完多少篇解题报告就要  请吃饭。。。所以我就开始写了,是不是被我的决心所折服了呢。再见

  

 好了开始写了。

 题目大意:有n个物品,体积分别为Li,每个箱子的容积都一样且为M。每个箱子最多装两个物品,  使得所装物品能够装得下。问最少用几个箱子把所有物品装完?

 ---------------------------------------------------------------

  这个很明显是一个贪心,将物品体积从大到小排序。注意到,我们试图用重大的物品去匹配体积最小的物品,如果体积和小于M,那么这个箱子可以装两个;否则只能装大的那个。有的人会顾虑,是否需要找一个物品使得它与当前最大物品尽量填满箱子,以保证后面最优。这是没必要的,因为既然这个箱子可以与最大箱子共存,就一定可以和以后的任何箱子共存,所以大可以放在后面使用。

  于是乎我们设置两个旗杆i和j分别指向第0个物品和第n-1个物品,数组w[i]表示第i个物品的体积,我们看w[i]+w[j]>=M?如果是就i++且j--(装两个物品),否则就只i++(装大的物品)。那么什么时候结束呢?当(i>j)结束,而非(i>=j),因为有可能出现最后i==j,那个物品仍然需要一个箱子。(有点类似快速排序的那种形式)。

  最后我们就上代码了。

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <sstream>
#include <cstdio>
using namespace std;

int maxloc(int a[], int l, int r)
{
	int key = l;
	for ( int i = l; i <= r; i++)
	{

		if (a[i] >= a[key])
			key = i;
	}
	return key;
}

struct pank
{
	int loc;
	int size;
	bool operator <(const pank& rhs)const
	{
		return size < rhs.size;
	}
};

void SWAP(int a[], int l, int r)
{
	int i = l, j = r;
	while (i < j)
	{
		int tem = a[i];
		a[i] = a[j];
		a[j] = tem;
		i++; j--;
	}
}

pank pan[40];
int Rank[40];
pank tem[40];

int main()
{
	for (string strLine; getline(cin,strLine);)
	{
		cout << strLine << endl;
		istringstream iss(strLine);
		int n = 0;
		while (iss >> pan[n].size)
		{
			pan[n].loc = n;
			tem[n] = pan[n];
			n++;
		}
		if (n == 0)
			break;
		sort(tem, tem + n);
		int ans = 0;
		for (int i = 0; i < n; i++)
			Rank[tem[i].loc] = i;
					
		for (int i = n-1; i >=0; i--)
		{
			int key = maxloc(Rank, 0, i);
			if (key != i)
			{
				if (key != 0)
				{
					SWAP(Rank, 0, key);
					cout << n - key << " ";
				}
				SWAP(Rank, 0, i);
				cout << n- i << " ";
			}
			
		}
		cout << 0 << endl;
	}
	return 0;
}


  话说这个题似乎在UVA上数据有问题,但也不肯定,求大神真相一下。囧。。

  最后祝愿我们嗑瓜子队伍可以越来越棒~~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值