题意:题意:有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; } }