题意:题意:有t组测试数据。每组测试数据有4个数据,分别表示要买几瓶可乐,分别有多少个价值为1,5,10的硬币。每瓶可乐价值为8。问最少需要给自动贩卖机投多少枚硬币。注意,投入硬币后,自动贩卖机会用最少的硬币数给你多的钱。
如果我们开四维的数组,是开不下的,考虑到买了一听可乐之后,价值总是下降的(虽然它的硬币组合是不同的),所以这个状态可以不用记录,只用来判断什么时候结束。注意有一个转移,如果投三个价值1的硬币和一个价值为10的硬币,可以得到一个价值为5的硬币,在一些情况下是可以减少投硬币的个数的。题目给出的数据范围有点问题,一直RE,直到开到这么多。。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int map[720][220][100];
bool vis[720][220][100];
int dp(int,int,int,int);
int main()
{
//freopen("10626","r",stdin);
int t;
scanf("%d",&t);
while(t--)
{
memset(map,0,sizeof(map));
memset(vis,0,sizeof(vis));
int c,n[3]={0};
scanf("%d%d%d%d",&c,&n[0],&n[1],&n[2]);
printf("%d\n",dp(c,n[0],n[1],n[2]));
}
return 0;
}
int dp(int c,int n1,int n2,int n3)
{
bool &flag=vis[n1][n2][n3];
int &res=map[n1][n2][n3];
if(flag) return res;
else if(c==0) {flag=1;res=0;return 0;}
else
{
res=1<<30;
if(n1>=8) res=min(res,dp(c-1,n1-8,n2,n3)+8);
if(n1>=3&&n2>=1) res=min(res,dp(c-1,n1-3,n2-1,n3)+4);
if(n1>=3&&n3>=1) res=min(res,dp(c-1,n1-3,n2+1,n3-1)+4);
if(n2>=2) res=min(res,dp(c-1,n1+2,n2-2,n3)+2);
if(n3>=1) res=min(res,dp(c-1,n1+2,n2,n3-1)+1);
flag=1;return res;
}
}