cf 853 D Michael and Charging Stations [dp]

题面:

传送门

思路:

看到题目,第一思路是贪心,但是我很快就否决掉了(其实分类贪心也可以做)

然后就想,贪心不能解决的状态缺失,是否可以用dp来解决呢?

事实证明是可以的

我们设dp[i][j]表示第i天,还剩j*100积分的时候,最小花费的现金

有转移:dp[i][j]=min(dp[i-1][k]+cost[i]-(k-j)*100)(k=j+1...min(30,j+cost[i]/100)

最后再dp[i][j]=min(dp[i][j],dp[i-1][j-cost[i]/1000]+cost[i])

这里k的上限是30是因为最多攒3000积分以后就必须要花掉,不然也不会更加划算(支付1000+2000)(证明太长了......)

Code:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define inf 1e9
 6 using namespace std;
 7 inline int read(){
 8     int re=0,flag=1;char ch=getchar();
 9     while(ch>‘9‘||ch<‘0‘){
10         if(ch==‘-‘) flag=-1;
11         ch=getchar();
12     }
13     while(ch>=‘0‘&&ch<=‘9‘) re=(re<<1)+(re<<3)+ch-‘0‘,ch=getchar();
14     return re*flag;
15 }
16 int n,a[300010];
17 int dp[300010][31];
18 int main(){
19     int i,j,k,ans=inf;
20     n=read();
21     for(i=1;i<=n;i++) a[i]=read();
22     for(i=1;i<=30;i++) dp[0][i]=inf;
23     for(i=1;i<=n;i++){
24         for(j=0;j<=30;j++){
25             dp[i][j]=inf;
26             for(k=min(30,j+a[i]/100);k>j;k--){
27                 dp[i][j]=min(dp[i][j],dp[i-1][k]+a[i]-(k-j)*100);
28             }
29             if(j>=a[i]/1000) dp[i][j]=min(dp[i][j],dp[i-1][j-a[i]/1000]+a[i]);
30 //            cout<<i<<ends<<j<<ends<<dp[i][j]<<endl;
31         }
32     }
33     for(i=0;i<=30;i++) ans=min(ans,dp[n][i]);
34     printf("%d\n",ans);
35 }

原文地址:https://www.cnblogs.com/dedicatus545/p/8453821.html

时间: 2024-09-30 21:45:26

cf 853 D Michael and Charging Stations [dp]的相关文章

Codeforces Round #433 (Div. 1) D. Michael and Charging Stations(dp)

题目链接:Codeforces Round #433 (Div. 1) D. Michael and Charging Stations 题意: 一个人每天要加油,1种为1000,1种为2000,如果付全额,会得到10%的回扣放在卡上. 如果卡上有剩余的回扣,可以拿来抵现金.问n天最少需要花多少钱. 题解: 很直观的一个dp就是考虑dp[i][j],表示第i天卡上剩余回扣为j的最小花费. 将所有的数除以100后,j其实是小于40的,严格的说是小于30,官方题解有个证明. 因为卡上不可能积累很多的

codeforces:Michael and Charging Stations分析和实现

题目大意 迈克尔接下来n天里分别需要支付C[1], C[2], ... , C[n]费用,但是每次支付费用可以选择使用优惠或不使用优惠,每次使用价值X的优惠那么迈克尔所能使用的优惠余量将减少X并且当天所需要支付的费用将减少X,而第一天迈克尔所持有的优惠余量为0.如果不使用优惠,那么优惠余量将增加X/10,其中X是当天迈克尔所支付的费用. 输入规模为1<=n<=3e5,而C[1], ... , C[n]只可能取1000或2000. 思路 下面说明一下我个人的思路: 一个解决方案可以归结为每日所使

CF 219D Choosing Capital for Treeland 树形DP 好题

一个国家,有n座城市,编号为1~n,有n-1条有向边 如果不考虑边的有向性,这n个城市刚好构成一棵树 现在国王要在这n个城市中选择一个作为首都 要求:从首都可以到达这个国家的任何一个城市(边是有向的) 所以一个城市作为首都,可能会有若干边需要改变方向 现在问,选择哪些城市作为首都,需要改变方向的边最少. 输出最少需要改变方向的边数 输出可以作为首都的编号 树形DP 先假定城市1作为首都 令tree(i)表示以i为根的子树 dp[i]表示在tree(i)中,若以i为首都的话,需要改变的边数 第一次

(中等) CF 311B Cats Transport,斜率优化DP。

Zxr960115 is owner of a large farm. He feeds m cute cats and employs p feeders. There's a straight road across the farm and n hills along the road, numbered from 1 to n from left to right. The distance between hill i and (i - 1) is di meters. The fee

CF# 149 D Coloring Brackets(区间dp)

D - Coloring Brackets Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 149D Description Once Petya read a problem about a bracket sequence. He gave it much thought but didn't find a solut

cf 540D D. Bad Luck Island 概率dp

D. Bad Luck Island time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output The Bad Luck Island is inhabited by three kinds of species: r rocks, s scissors and p papers. At some moments of time two

cf 398B. Painting The Wall【期望dp】

传送门:http://codeforces.com/problemset/problem/398/B Description: User ainta decided to paint a wall. The wall consists of n2 tiles, that are arranged in an n?×?n table. Some tiles are painted, and the others are not. As he wants to paint it beautifull

CF 429B B.Working out (四角dp)

题意: 两个人一个从左上角一个从左下角分别开始走分别走向右下角和右上角,(矩阵每个格子有数)问到达终点后可以得到的最大数是多少,并且条件是他们两个相遇的时候那个点的数不能算 思路: 首先这道题如果暴力搜索一般是gg了,所以考虑动态规划 我们设起点为st(1,1),终点为ed(n,m),相遇的点为now(i,j) 问题转化为计算st→now + now→ed的值(不包含now) 这个问题可以分解为求st→now和now→ed的值,st→now = dp[st][now],那么now→ed怎么求呢

cf 319 div 2 Modulo Sum 数论+DP

 Modulo Sum 题目抽象:给你你一个整数数组,能否从中取出一些树,使得他们的和能被m整除. 分析:见代码注释. 1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 const int MS = 1000005; 5 int n, m; 6 int cnt[MS], r[MS], tem[MS]; 7 int main() { 8 scanf("%d%d", &n, &