TOJ 4303


题目连接:

http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=4303


题目类型:

动态规划 - 多重01背包


数据结构:

struct LMIC_CNT
{
	int cnt;
	int bls[102];
} cnt[32001];

 
思想分析:

-----------------------------------------------------
贪心思路:

既然要求搭N高度的时候最少的积木

直接从最高的积木入手,用完最高的积木用第二高的积木,

这种思想在求只要高过指定高度H的时候才有用,

对于达到指定高度则不能在任何情况都正确


-----------------------------------------------------
广度优先思路:

第一步从M个积木开始,

讲第一步的M个积木都压入队列,

下一步都从该步骤中队列最高且还有的积木入手进行拓展,

每个节点都记录所有积木的使用情况.

直到搜索到等于该高度的情况为止.

但是由于需要搜索所有的情况的点,

所以容易超时超内存;


-----------------------------------------------------
动态思路:

既然求在搭建N高度的最少积木,

不妨从高度=1的情况开始做起,

利用现有积木,求从1到N的所有情况.

当需要求K高度的最少木块时(1

让K减去剩余所有木块,看哪种情况是需要最少块数的,

并记录下来,当下一层需要求该层的最少块数,直接调用即可



证明:



源代码:

#include 
#include 
#include 
#include 
using namespace std;

struct LMIC_CNT
{
	int cnt;
	int bls[102];
} cnt[32001];

void _dpboock(int b[13][2],int n,int t,LMIC_CNT *c)
{
	int i,j,k;
	
	// 初始化 
	c[0].cnt=0;
	for(i=1;i<=n;i++) c[0].bls[i]=b[i][1];
	
	for(i=1;i<=t;i++)
	{
		int minc=INT_MAX;
		
		if(i==14)
		printf(""); 
		
		for(j=1;j<=n;j++)
		{
			if(b[j][0]<=i && c[i-b[j][0]].bls[j]>0)
			{
				//当前面值最小找法,等于减去一种面值硬币剩下找法+1;
				//当前面值减去一种面值时,需要检查该面值是否还有剩余 
				int temp=c[i-b[j][0]].cnt+1;

				if(minc>=temp)
				{
					minc=temp;
					for(k=1;k<=n;k++)
						c[i].bls[k]=c[i-b[j][0]].bls[k];
					c[i].bls[j]--;
				}
			}
		}
		c[i].cnt=minc;
	}
	printf("%d\n",c[i-1].cnt);
}

int main()
{
	int i,n,t,blos[14][2]={0};
	
	while(scanf("%d",&n)!=EOF)
	{
		for(i=1;i<=n;i++) scanf("%d%d",&blos[i][0],&blos[i][1]);
		
		scanf("%d",&t);
		
		memset(cnt,0,sizeof(cnt));
		
		_dpboock(blos,n,t,cnt);
	}
	return 0;
}



你可能感兴趣的:(ACM解题报告)