题目大意:有个贩卖机卖可乐,每次只能买一次可乐,找零的时候他会按照最少的硬币数进行找零,要求买N瓶可乐,每瓶可乐价值为8,有三种硬币,价值分别为1,5,10,钱时够用的,问买N瓶可乐时往贩卖机丢入硬币的最小值
解题思路:这题的状态比较多,有四个,可乐的数量,三种硬币的数量,共有四个,舍去一个的可乐的数量的话,那还有三个,就用三维数组表示三种硬币的数量的状态,设dp[i][j][k]为价值1的硬币还有i个,5的有j个,10的有k个的丢入硬币的最低值。买可乐的话有5种买卖方式
1.1个十的找回2个一的
2.1个十的3个一的找回1个五的
3.2个五的找回2个一的
4.1个五的3个一的
5.8个一的
这五种是最优的选择
#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
int dp[750][220][100];
bool vis[750][220][100];
int solve(int c,int n1,int n5,int n10) {
int &res = dp[n1][n5][n10];
bool &flag = vis[n1][n5][n10];
if(flag)
return res;
else if(c == 0) {
flag = 1;
res = 0;
return res;
}else {
res = INF;
if(n1 >= 8)
res = min(res,solve(c-1,n1-8,n5,n10) + 8);
if(n5 >= 1 && n1 >= 3)
res = min(res,solve(c-1,n1-3,n5-1,n10) + 4);
if(n10 >= 1 && n1 >= 3)
res = min(res,solve(c-1,n1-3,n5+1,n10-1) + 4);
if(n5 >= 2)
res = min(res,solve(c-1,n1+2,n5-2,n10) + 2);
if(n10 >= 1)
res = min(res,solve(c-1,n1+2,n5,n10-1) + 1);
flag = 1;
return res;
}
}
int main() {
int test;
scanf("%d",&test);
while(test--) {
int c,coin[3];
scanf("%d%d%d%d",&c,&coin[0],&coin[1],&coin[2]);
memset(vis,0,sizeof(vis));
printf("%d\n",solve(c,coin[0],coin[1],coin[2]));
}
return 0;
}