题意:
已知接下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;
}