解题报告:Codeforces Round #433 (Div. 1) D. Michael and Charging Stations (DP)

题目链接

题意:

已知接下n天每天的消费ai

若某一天只使用现金,则可以得到10%的消费作为代金券

询问度过这n天的最小花费

n<=3e5,ai={1000,2000}


思路:

dp[x][y]:第 x 天手上有y金额的代金券所需的最小花费

将ai除以100以缩小第二维的大小,那么可以确定y<=10+20+1=31

因为使用代金券会无法得到代金券,所以每次使用时要尽可能的大

得到递推方程:

当只使用现金时:

使用代金券时:

总复杂度O(31*n)

代码:

#include<bits/stdc++.h>
#define INF dp[0][32]
const int N = 3e5+10;
using namespace std;

int n,A[N];
int dp[2][35];

int main()
{
   memset(dp,0x3f,sizeof(dp));
   scanf("%d",&n);
   for(int i=1;i<=n;++i){
      scanf("%d",&A[i]);A[i]/=100;
   }int s = 0 , t = 1;dp[0][0] = 0;
   for(int i=1;i<=n;++i){ int a = A[i] / 10;
      for(int j=0;j<=31;++j)if(dp[s][j]<INF){
         if(j+a<=31)dp[t][j+a] = min(dp[t][j+a],dp[s][j]+A[i]);
         int b = min(j,A[i]);
         if(b)dp[t][j-b] = min(dp[t][j-b],dp[s][j]+A[i]-b);
         dp[s][j] = INF;
      }swap(s,t);
   }int ans = INF;
   for(int i=0;i<20;++i)ans = min(ans,dp[s][i]);
   printf("%d00\n",ans);
   return 0;
}







  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值