10626 - Buying Coke

来源:互联网 发布:安装nodejs mac 命令行 编辑:程序博客网 时间:2024/05/22 07:58

憋了好几天在雪哥的指点下终于过了,第一次些这样奇怪的dp……

刚开始没有考虑到(10, 3 *1)可以兑换一瓶coca和一个5分硬币这种情况,以为不用动规,用贪心就行,结果老是WA,很不解,后来终于了发现这种情况。

想用动规解,刚开始定义状态f[p][i][j][k]表示i个1分,j个5分,k个10分买p瓶coca所投的最少的硬币数,但发现开不开,然后就没怎么想。后来问雪哥,定义状态应该减少一维,p

这个状态不要了。其实没怎么理解明白,然后就写,写了2个多小时,终于调好了,交上后TLE,实在想不出什么优化,然后又问了一遍,确实自己理解错了,改了改,不到40行代码就AC了,这代码量真对不起我的劳动……

定义状态f[i][j][k]表示i个1分,j个5分,k个10分买C瓶coca所投的最少的硬币数,这个C是隐含的,dp的时候才体现出来,这就是为什么说dp奇怪了……状态转移方程有5种:投(1 * 8), (5 *1, 1 * 3),(5 * 1,5 *1),(10 * 1),(10 * 1, 1 * 3)这5种转移,便可得到结果。

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int INF = (1<<29);int V, res, f[702][152][52], d[702][152][52];int a[3];int dp(int i, int j, int k, int x){    if(x == 0) return 0;    int & ans = f[i][j][k];    if(ans != -1) return ans;    ans = INF;    if(i >= 8)        ans = min(ans, dp(i - 8, j, k, x - 1) + 8);    if(i >= 3 && j >= 1)        ans =  min(ans, dp(i - 3, j - 1, k, x - 1) + 4);    if(j >= 2)        ans = min(ans, dp(i + 2, j - 2, k, x - 1) + 2);    if(k >= 1)        ans = min(ans, dp(i + 2, j, k - 1, x - 1) + 1);    if(i >= 3 && k >= 1)        ans = min(ans, dp(i - 3, j + 1, k - 1, x - 1) + 4);    return ans;}int main(){    //freopen("input.txt", "r", stdin);    int nCase;    scanf("%d", &nCase);    while(nCase--){        scanf("%d %d %d %d",  &V, &a[0], &a[1], &a[2]);        memset(f, -1, sizeof(f));        printf("%d\n", dp(a[0], a[1], a[2], V));    }    return 0;}

原创粉丝点击