题目连接:
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 <iostream>
#include <stdio.h>
#include <math.h>
#include <queue>
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;
}