Time Limit : 1000/500ms (Java/Other) Memory Limit : 131072/65536K (Java/Other)
Problem Description
Due to the preparation to the wedding you have to fill up M balloons. There are N volunteers and one device for balloons filling up. Device can fill at most one balloon at a time. Each volunteer can continuously operate the device for 1 minute.
Volunteer number i can fill Ai balloons during one minute and then he or she must have at least Bi minutes of rest.
You are to write a program that computes minimal possible time of filling up M balloons.
Input
There are two integers M and N on the first line (1 <= M <= 100, 1 <= N <= 10).
Next N lines contain two integers each: Ai and Bi (0 <= Ai <= 10, 1 <= Bi <= 4).
Output
Print one integer T - the minimal number of minutes required to filling M balloons.
Sample test(s)
Input
10 3
4 4
3 4
2 3
Output
5
题意:N(1<=N<=10)个人一台装置填充M(1<=M<=100)个气球,每个人一分钟能充Ai个(0<=Ai<=10),休息Bi(1<=Bi<=4)分钟后才可以继续充气球,文填充M个气球最少需要多少时间?
分析:看到题目,第一想法就是排序,先大后小,然后DFS,这样显然错的,样例都过不了,然后又想着暴力写出来,不行,肯定会超时,只给了0.5s。
然后无奈看了大佬写的博客,他就直接观察到了Bi的范围,是1到4,这个很小,可以开一个五维数组ans[sum][a][b][c][d]来表示还剩sum个气球,前一分钟是a在充气球,前两分钟是b在充气球,前3分钟是c在充气球,前4分钟是d在吹气球,然后直接记忆化搜索
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=11,INF=0x3f3f3f3f;
int ans[101][N][N][N][N],A[N],B[N];
int n,m,res;
int dfs(int sum,int a,int b,int c,int d)
{
if(sum<=0) sum=0;///全部充完
if(ans[sum][a][b][c][d]!=INF) return ans[sum][a][b][c][d];///还剩sum个球所用的最短时间已找到
if(sum==0) ans[sum][a][b][c][d]=0;///全部填充完毕
else
{
int flag=0;
for(int i=1; i<=n; i++)
{
if(a==i&&B[i]>0) continue;
if(b==i&&B[i]>1) continue;
if(c==i&&B[i]>2) continue;
if(d==i&&B[i]>3) continue;
flag=1;
int t=dfs(sum-A[i],i,a,b,c);///第i人在充气球
ans[sum][a][b][c][d]=min(ans[sum][a][b][c][d],t+1);///+1是因为最后还有一个人在充
}
if(!flag)///都在休息
{
int t=dfs(sum,0,a,b,c);
ans[sum][a][b][c][d]=min(ans[sum][a][b][c][d],t+1);
}
};
return ans[sum][a][b][c][d];
}
int main()
{
scanf("%d%d",&m,&n);
memset(ans,INF,sizeof(ans));
for(int i=1; i<=n; i++)
scanf("%d%d",&A[i],&B[i]);
res=dfs(m,0,0,0,0);
printf("%d\n",res);
return 0;
}
写这题的时候那个oj的判题有问题,我写错了一个地方,导致样例都过不了,还AC了。。。。。 不过这个思路应该没问题
如有不对的地方,烦请大佬指出,谢谢
小结:像这类题,观察数据范围,比如数组B,范围小,就能开一个数组记忆最少时间,然后和DFS结合。
自己对记忆化搜索不太感冒,还要勤加练习。