本题的大意是:取款机取款,取款机会给出低于或等于指定金额的钱。
看了一下讨论区,铺天盖地的背包算法,我表示背包九讲看了一点,还不是很理解,只能用别的了。开始准备用DP但是想了半天,没有想出定义什么样的状态比较好,只能作罢。只好暴力搜索了,搜索的策略是从cash开始往前搜索。但是没有剪枝肯定是TLE的,如何剪枝呢?对于每一个cash记录每一次失败搜索的值,如果下次再搜索到这个值,直接返回false;只有这一个剪枝,最终的结果650ms,只能说恰强人意。研究了一下,发现第一次cash有一个最小的搜索值min,可以下一次搜索从(cash-min)开始,最后结果16ms。
#include <stdio.h>
#include <string.h>
int count;
int min;
int cash;
int D[20];
int N[20];
int totals[100010];
int search(int left);
int main()
{
int i;
while(scanf("%d %d",&cash,&count)!=EOF)
{
for(i=0;i<count;i++)
scanf("%d %d",&N[i],&D[i]);
if(cash==0 || count==0)
{
printf("0\n");
continue;
}
for(i=cash;i>=0;)
{
memset(totals,0,sizeof(totals));
min=100000;
if(search(i))
break;
i-=min;
}
printf("%d\n",i);
}
return 0;
}
int search(int left)
{
int i;
if(totals[left]==1)
return 0;
for(i=0;i<count;i++)
{
if(D[i]>left || N[i]==0)
continue;
N[i]--;
if(D[i]==left || search(left-D[i]))
return 1;
if(min>(left-D[i]))
min=left-D[i];
totals[left-D[i]]=1;
N[i]++;
}
return 0;
}