题目2 : Disk Storage
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
Little Hi and Little Ho have a diskstorage. The storage's shape is a truncated cone(截头圆锥体) of height H. R+H is radius oftop circle and R is radius of base circle.
Little Ho buys N disks today. Every disk is a cylinder of height 1. Little Howants to put these disk into the storage under below constraints:
1. Every disk is placed horizontally. Itsaxis must coincide with the axis of storage.
2. Every disk is either place on the bottom surface or on another disk.
3. Between two neighboring disks in the storage, the upper one's radius minusthe lower one's radius must be less than or equal to M.
Little Ho wants to know how many disks hecan put in the storage at most.
输入
Input contains only one testcase.
The first line contains 4 integers: N(1 <= N <= 100000), M, H, R(1 <=M, R, H <= 100000000).
The second line contains N integers, each number prepresenting the radius of adisk. Each radius is no more than 100000000.
输出
Output the maximum possible number of diskscan be put into the storage.
样例输入
5 1 10 3
1 3 4 5 10
样例输出
4
基本思想就是穷举和递归,因为每选出一个盘子就相当于在R+1,H-1的子空间里放剩下的盘子。
以下内容是我的C++实现,由于本人水平有限,代码肯定存在不合理的地方,欢迎读者能提出意见。
文件1:disk_storage.h
#ifndef _DISK_STORAGE_H_
#define _DISK_STORAGE_H_
class DISKS_CL
{
public:
DISKS_CL(int _iN);
~DISKS_CL();
DISKS_CL(const DISKS_CL& _clDisks);
DISKS_CL& operator=(const DISKS_CL& _clDisks);
int GetDiskByIndex(int iIndex) const;//获取一个盘子的半径
void DeleteDiskByIndex(int iIndex);//删除一个盘子的半径数据
int GetDiskNum() const;//获取问题中盘子的总数
private:
int iN;//disk number
int *piRadius;//all radius
void Input();//输入所有盘子的半径数据
};
class STORAGE_CL
{
public:
STORAGE_CL();
~STORAGE_CL();
void Input();//输入数据
int GetDiskNum();//获取问题中盘子的总数
int FindMax(DISKS_CL& clDisks);//找出满足条件的最大存放数目
private:
int iN;
int iH;
int iR;
int iM;
//递归函数
int DoFind(int _iH, int _iR, int _iPreIndex, DISKS_CL clDisks);
};
#endif
文件2:disk_storage_main.cpp
#include <iostream>
#include "disk_storage.h"
using namespace std;
STORAGE_CL::STORAGE_CL():iN(0),iH(0),iR(0),iM(0)
{
Input();
return;
}
STORAGE_CL::~STORAGE_CL()
{
return;
}
void STORAGE_CL::Input()
{
cin>>iN>>iM>>iH>>iR;
return;
}
int STORAGE_CL::GetDiskNum()
{
return iN;
}
int STORAGE_CL::FindMax(DISKS_CL& clDisks)
{
return DoFind(iR,iH,-1,clDisks);
}
int STORAGE_CL::DoFind(int _iR, int _iH, int _iPreIndex, DISKS_CL clDisks)
{
int i;
int iRadius;
int iResult;
int iRet;
int iPreRadius;
if (0 == _iH)//没有空间了
{
return 0;
}
if (-1 == _iPreIndex)//第一个盘子
{
iPreRadius = iRadius - iM;
}
else//以后的盘子
{
iPreRadius = clDisks.GetDiskByIndex(_iPreIndex);
clDisks.DeleteDiskByIndex(_iPreIndex);
}
iResult = 0;
for (i=0; i<iN; i++)//对所有盘子循环
{
iRadius = clDisks.GetDiskByIndex(i);
if (0 == iRadius)//跳过之前处理过的盘子
{
continue;
}
if (iRadius <= _iR && iRadius-iPreRadius >= iM)//满足条件则试取出这个盘子
{
iRet = DoFind(_iR+1, _iH-1, i, clDisks);
if (iRet >= iResult)//记录这次循环中的最大结果
{
iResult = iRet + 1;
}
}
}
return iResult;
}
DISKS_CL::DISKS_CL(int _iN)
{
iN = _iN;
piRadius = new int[iN];
Input();
}
DISKS_CL::~DISKS_CL()
{
if (NULL != piRadius)
{
delete piRadius;
}
return;
}
DISKS_CL::DISKS_CL(const DISKS_CL& _clDisks)
{
int i;
iN = _clDisks.GetDiskNum();
piRadius = new int[iN];
for (i=0; i<iN; i++)
{
piRadius[i] = _clDisks.GetDiskByIndex(i);
}
return;
}
DISKS_CL& DISKS_CL::operator=(const DISKS_CL& _clDisks)
{
int i;
iN = _clDisks.GetDiskNum();
piRadius = new int[iN];
for (i=0; i<iN; i++)
{
piRadius[i] = _clDisks.GetDiskByIndex(i);
}
return *this;
}
int DISKS_CL::GetDiskByIndex(int iIndex) const
{
return piRadius[iIndex];
}
void DISKS_CL::DeleteDiskByIndex(int iIndex)
{
piRadius[iIndex]=0;
return;
}
int DISKS_CL::GetDiskNum() const
{
return iN;
}
void DISKS_CL::Input()
{
int i;
for (i=0;i<iN;i++)
{
cin>>piRadius[i];
}
return;
}
int main()
{
int iNum;
STORAGE_CL clStorage;
DISKS_CL clDisks(clStorage.GetDiskNum());
iNum = clStorage.FindMax(clDisks);
cout<<iNum<<endl;
return 0;
}
运行结果:
hc@ubuntu:~/Workspace/ms_proj/src$ ./run_disk_storage
5 1 10 3
1 3 4 5 10
4
hc@ubuntu:~/Workspace/ms_proj/src$ ./run_disk_storage
6 2 10 3
1 2 3 4 5 6
3