Codeforces 358D. Dima and Hares (dp)

题目链接:

http://codeforces.com/problemset/problem/358/D

题意:

给出n个数,每个数取走的贡献与相邻的数有关,如果取这个数的时候,左右的数都还没被取,那么权值为a,如果左右两个数有一个被取走了,那么权值为b,如果左右两个数都被取走了,那么权值为c,求取取走全部数的最大值。

思路:

from: http://blog.csdn.net/qq_24451605/article/details/48896657

定义状态:

    • dp[i][1][0]表示选第i时,相邻的数有一个被取走,这个数在当前数左侧。
    • dp[i][1][1]表示选第i时,相邻的数有一个被取走,这个数在当前数右侧。
    • dp[i][2][0]表示选第i时,相邻的数都被取走了
    • dp[i][0][0]表示选第i时,相邻的数都没被取走

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define MS(a) memset(a,0,sizeof(a))
#define MP make_pair
#define PB push_back
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
//////////////////////////////////////////////////////////////////////////
const int maxn = 3e3+10;

int n,a[maxn],b[maxn],c[maxn],dp[maxn][3][2];

int main(){
    cin >> n;
    for(int i=1; i<=n; i++)
        cin >> a[i];
    for(int i=1; i<=n; i++)
        cin >> b[i];
    for(int i=1; i<=n; i++)
        cin >> c[i];

    memset(dp,-INF,sizeof(dp));
    dp[1][0][0] = a[1];
    dp[1][1][1] = b[1];
    dp[1][1][0] = dp[1][2][0] = -INF;
    for(int i=2; i<=n; i++){
        dp[i][0][0] = max(dp[i-1][1][1],dp[i-1][2][0])+a[i];
        dp[i][1][0] = max(dp[i-1][1][0],dp[i-1][0][0])+b[i];
        dp[i][1][1] = max(dp[i-1][1][1],dp[i-1][2][0])+b[i];
        dp[i][2][0] = max(dp[i-1][1][0],dp[i-1][0][0])+c[i];
    }
    cout << max(dp[n][0][0],dp[n][1][0]) << endl;

    return 0;
}
时间: 2024-10-17 20:37:55

Codeforces 358D. Dima and Hares (dp)的相关文章

CodeForces 358D — Dima and Hares

这题要备忘一下,对于简单的偏序关系对应的价值也可以施行dp. /* ID:esxgx1 LANG:C++ PROG:cf358D */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 3007; unsigned joy[maxn][3]; unsigned dp[2][2];

Codeforces 360C Levko and Strings dp

题目链接:点击打开链接 题意: 给定长度为n的字符串s,常数k 显然s的子串一共有 n(n-1)/2 个 要求找到一个长度为n的字符串t,使得t对应位置的k个子串字典序>s #include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> #include<vector> #include<set> using namespace std; #

CodeForces 30C Shooting Gallery 简单dp

题目链接:点击打开链接 给定n个气球 下面n行 x y t val 表示气球出现的坐标(x,y) 出现的时刻t,气球的价值val 枪每秒移动1个单位的距离 问: 射击的最大价值,开始时枪瞄准的位置任意. 思路: dp一下.. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <math.h> #include <set

Codeforces 459E Pashmak and Graph(dp+贪心)

题目链接:Codeforces 459E Pashmak and Graph 题目大意:给定一张有向图,每条边有它的权值,要求选定一条路线,保证所经过的边权值严格递增,输出最长路径. 解题思路:将边按照权值排序,每次将相同权值的边同时加入,维护每个点作为终止点的最大长度即可. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 3

codeforces 149D - Coloring Brackets (区间dp)

题目大意: 给出一组合法的括号. 括号要么不涂颜色,要么就涂上红色或者绿色. 匹配的括号只能有一个有颜色. 两个相邻的括号不能有相同的颜色. 思路分析: 因为是一个合法的括号序列. 所以每个括号与之匹配的位置是一定的. 那么就可以将这个序列分成两个区间. (L - match[L] )  (match[L]+1, R) 用递归先处理小区间,再转移大区间. 因为条件的限制,所以记录区间的同时,还要记录区间端点的颜色. 然后就是一个递归的过程. #include <cstdio> #include

CodeForces 55D Beautiful numbers 数位DP+数学

题意大概是,判断一个正整数区间内有多少个整数能被它自身的每一个非零的数字整除. 因为每一个位置上的整数集s = {0,1,2,3,4,5,6,7,8,9} lcm(s) = 2520 现在有一个整数t是由s中一个或者多个数字构成的,记为abcde,显然t = a*10^4+b*10^3+c*10^2+d*10^1+e 要使得t能被a,b,c,d,e整除,必然有t % lcm(a,b,c,d,e) = 0 因为a,b,c,d,e去重之后一定是s的一个子集,所以lcm(s)一定是lcm(a,b,c,

codeforces 366C C. Dima and Salad(dp)

题目链接: codeforces 366C 题目大意: 给出n个物品,有两个属性,问最后第一个属性的总和是第二个属性的k倍的时候,第一个属性最大是多少. 题目分析: 我们将物品做一个变形,重量为a[i]-b[i]*k,收益是a,那么我们只需要对重量为正的做一遍背包,对质量为负的取绝对值做一遍背包,然后重量相等的背包的收益之和就是当前重量下的最大收益. AC代码: #include <iostream> #include <cstring> #include <cstdio&g

Codeforces 833B 线段树优化 dp

Codeforces  833B  The Bakery 题意: n 个数要分成 k 块,每块的价值是其不同数的个数,问价值和最大是多少. tags: dp[i][j]表示前 j 个数分成 i 块的最大权值和,转移: dp[i][j] = max( dp[i-1][k] + val[k+1][j] ) , k是 1~j . 但这个过程其实并不好转移,要利用累加的特点,用线段树进行优化 (感觉我不看题解是想不到的,2333) 大概就是,对于第 i 层,我们假定已经知道了第 i-1 层,也就是求出了

Codeforces 803E--Roma and Poker (DP)

原题链接:http://codeforces.com/problemset/problem/803/E 题意:给一个n长度的字符串,其中'?'可以替换成'D'.'W'.'L'中的任意一种,'D'等价于0, 'W'等价于1.'L'等价于-1.输出所有'?'被替换掉后,W和L的数目之差为k,且任意一个[1, i]的子串中W和L数目之差不能等于k. 思路:用DP做.定义bool dp[i][j]代表前i个字符W和L数目之差为j, -k<=j<=k(在数组中范围为[0, 2*k]),那么当str[i]