leetcode-商店促销活动(DP GOOD)

#

  • 有时候结合题目条件,求出所有dp值,最后再筛选满足条件的部分

思路

  • 分类讨论:A购买3件及以上,A未购买3件以上
  • d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k],处理到第i件商品,A累计已经购买j件(如果j>=3,那么j=3),B当前状态为k件(k = 0,1,2)时价格的最小值
  • A购买3件以上:从初始开始转移,只不过最后只取j=3,即 d p [ n ] [ 3 ] [ k ] , k ∈ 0 , 1 , 2 dp[n][3][k],k\in 0,1,2 dp[n][3][k]k012.打7折的处理:转移过程中A的所有价格乘以7,B的所有价格乘以10.
    • 条件是到达末尾A的总件数必须>=3
    • 最后每个dp的价格除以10
  • A未购买3件以上:从初始开始转移即可,相当于忽略A打7折的条件


class Solution {
    typedef long long ll;
public:
    int goShopping(vector<int>& priceA, vector<int>& priceB) {
        array<ll,2> A[priceA.size()];
        array<ll,2> B[priceB.size()];
        for(ll i = 0;i<priceA.size();i++)
        {
            A[i][0] = (ll)priceA[i];
            A[i][1] = i;
            B[i][0] = (ll)priceB[i];
            B[i][1] = i;
        }
        sort(A,A+priceA.size(),[&](array<ll,2> a,array<ll,2> b){return B[a[1]][0] > B[b[1]][0];});
        sort(B,B+priceB.size(),[&](array<ll,2> a,array<ll,2> b){return a[0] > b[0];});
        ll n = priceA.size();
        ll dp[n+1][4][3];
        for(ll x = 0;x<4;x++)  
            for(ll y = 0;y<3;y++)
                dp[1][x][y] = INT_MAX;
        //第一次转移,乘7除以10
        dp[1][1][0]=A[0][0] *7;
        dp[1][0][1]=B[0][0] *10;
        for(int i = 0;i<n;i++) cout << A[i][0] << endl;
        for(int i = 0;i<n;i++) cout << B[i][0] << endl;
        for(ll i = 2;i<n+1;i++)
        {
           dp[i][0][0] =  dp[i-1][0][2];                 //只能是在B买
           dp[i][0][1] =  dp[i-1][0][0] + B[i-1][0]*10;
           dp[i][0][2] =  dp[i-1][0][1] + B[i-1][0]*10;
           dp[i][1][0] =  min(dp[i-1][0][0] + 7*A[i-1][0],dp[i-1][1][2]);       //第i件在B买或在A买
           dp[i][1][1] = min(dp[i-1][0][1] + 7*A[i-1][0],dp[i-1][1][0] + 10 * B[i-1][0]);
           cout << dp[i][1][1] << endl;
           dp[i][1][2] = min(dp[i-1][0][2] + 7*A[i-1][0],dp[i-1][1][1] + 10 * B[i-1][0]);
           dp[i][2][0] =  min(dp[i-1][1][0] + 7*A[i-1][0],dp[i-1][2][2]);       //第i件在B买或在A买
           dp[i][2][1] = min(dp[i-1][1][1] + 7*A[i-1][0],dp[i-1][2][0] + 10 * B[i-1][0]);
           dp[i][2][2] = min(dp[i-1][1][2] + 7*A[i-1][0],dp[i-1][2][1] + 10 * B[i-1][0]);
           dp[i][3][0] =  min(dp[i-1][2][0] + 7 * A[i-1][0],min(dp[i-1][3][0] + 7*A[i-1][0],dp[i-1][3][2]));       //第i件在B买或在A买
           dp[i][3][1] = min(dp[i-1][2][1] + 7 * A[i-1][0],min(dp[i-1][3][1] + 7*A[i-1][0],dp[i-1][3][0] + 10 * B[i-1][0]));
           dp[i][3][2] = min(dp[i-1][2][2] + 7 * A[i-1][0],min(dp[i-1][3][2] + 7*A[i-1][0],dp[i-1][3][1] + 10 * B[i-1][0]));
            
            
        }
        ll ans = INT_MAX;




        for(ll y = 0;y<3;y++)
        {    ans = min(ans,dp[n][3][y]/10);
           
        }
        for(ll x = 0;x<4;x++)  
            for(ll y = 0;y<3;y++)
                dp[1][x][y] = INT_MAX;
        //第一次转移,乘7除以10
        dp[1][1][0]=A[0][0] ;
        dp[1][0][1]=B[0][0] ;
        for(ll i = 2;i<n+1;i++)
        {
           dp[i][0][0] =  dp[i-1][0][2];                 //只能是在B买
           dp[i][0][1] =  dp[i-1][0][0] + B[i-1][0];
           dp[i][0][2] =  dp[i-1][0][1] + B[i-1][0];
           dp[i][1][0] =  min(dp[i-1][0][0] + A[i-1][0],dp[i-1][1][2]);       //第i件在B买或在A买
           dp[i][1][1] = min(dp[i-1][0][1] + A[i-1][0],dp[i-1][1][0] + B[i-1][0]);
           dp[i][1][2] = min(dp[i-1][0][2] + A[i-1][0],dp[i-1][1][1] + B[i-1][0]);
           dp[i][2][0] =  min(dp[i-1][1][0] + A[i-1][0],dp[i-1][2][2]);       //第i件在B买或在A买
           dp[i][2][1] = min(dp[i-1][1][1] + A[i-1][0],dp[i-1][2][0] + B[i-1][0]);
           dp[i][2][2] = min(dp[i-1][1][2] + A[i-1][0],dp[i-1][2][1] + B[i-1][0]);
           dp[i][3][0] =  min(dp[i-1][2][0] +  A[i-1][0],min(dp[i-1][3][0] + A[i-1][0],dp[i-1][3][2]));       //第i件在B买或在A买
           dp[i][3][1] = min(dp[i-1][2][1] +  A[i-1][0],min(dp[i-1][3][1] + A[i-1][0],dp[i-1][3][0] + B[i-1][0]));
           dp[i][3][2] = min(dp[i-1][2][2] +  A[i-1][0],min(dp[i-1][3][2] + A[i-1][0],dp[i-1][3][1] + B[i-1][0]));
        }
        for(ll x = 0;x<3;x++)
        {
            for(ll y = 0;y<3;y++)
             ans = min(ans,dp[n][x][y]);
        }
        system("pause");
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值