Codeforces 706 C. Hard problem (dp)

题目链接:http://codeforces.com/problemset/problem/706/C

给你n个字符串,可以反转任意一个字符串,反转每个字符串都有其对应的花费ci。

经过操作后是否能满足字符串str[i]>=str[i-1],能就输出最小花费,不能输出-1。

dp[i][0] 表示不反转i的最小花费(str[i] >= str[i - 1] || str[i] >= reverse(str[i - 1]))

dp[i][1] 则表示反转i的最小花费...

初始dp[1][0] = 0, dp[1][1] = c[1]

要是dp[i][0/1]等于-1 就不能转移了

代码写的有点糟糕,还是太渣...

 1 //#pragma comment(linker, "/STACK:102400000, 102400000")
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstdlib>
 5 #include <cstring>
 6 #include <cstdio>
 7 #include <string>
 8 #include <vector>
 9 #include <cmath>
10 #include <ctime>
11 #include <list>
12 #include <set>
13 #include <map>
14 using namespace std;
15 typedef long long LL;
16 typedef pair <int, int> P;
17 const int N = 1e5 + 5;
18 string str[N];
19 LL num[N], inf = 1e15;
20 LL dp[N][2];
21
22 int main()
23 {
24     ios::sync_with_stdio(false);
25     int n;
26     cin >> n;
27     for(int i = 1; i <= n; ++i)
28         cin >> num[i];
29     for(int i = 1; i <= n; ++i)
30         cin >> str[i];
31     int ok = 0;
32     memset(dp, -1, sizeof(dp));
33     dp[1][0] = 0, dp[1][1] = num[1];
34     for(int i = 2; i <= n; ++i) {
35         string str1 = str[i - 1]; //未反转
36         reverse(str[i - 1].begin(), str[i - 1].end());
37         string str2 = str[i]; //未反转
38         reverse(str[i].begin(), str[i].end());
39         if(dp[i - 1][0] == -1 && dp[i - 1][1] == -1) {
40             ok = -1; //不行了
41             break;
42         }
43         if(dp[i - 1][0] != -1) {
44             if(str2 >= str1) {
45                 dp[i][0] = dp[i - 1][0];
46             }
47             if(str[i] >= str1) {
48                 dp[i][1] = dp[i - 1][0] + num[i];
49             }
50         }
51         if(dp[i - 1][1] != -1) {
52             if(str2 >= str[i - 1]) {
53                 dp[i][0] = min(dp[i - 1][1], dp[i][0] == -1 ? inf : dp[i][0]);
54             }
55             if(str[i] >= str[i - 1]) {
56                 dp[i][1] = min(dp[i - 1][1] + num[i], dp[i][1] == -1 ? inf : dp[i][1]);
57             }
58         }
59         str[i] = str2; //赋值未反转
60     }
61     if(ok == -1) {
62         cout << -1 << endl;
63     }
64     else if(dp[n][0] != -1 && dp[n][1] != -1) {
65         cout << min(dp[n][0], dp[n][1]) << endl;
66     }
67     else if(dp[n][0] != -1) {
68         cout << dp[n][0] << endl;
69     }
70     else if(dp[n][1] != -1) {
71         cout << dp[n][1] << endl;
72     }
73     else {
74         cout << -1 << endl;
75     }
76     return 0;
77 }

时间: 2024-12-17 07:38:01

Codeforces 706 C. Hard problem (dp)的相关文章

http://codeforces.com/contest/741/problem/B B. Arpa&#39;s weak amphitheater and Mehrdad&#39;s valuable Hoses

题意: 给出上限体重W 然后还给出每个人的体重wi 和 魅力值 bi 互为伙伴的对(xi, yi) 可以凑成group 思路: 并查集找出所有的group 暴力背包 对于每一个group 要选出这一组内选一个人时的最优结果, 如果所有人的体重和小于等于W,还得考虑选所有人的情况 #include <iostream> #include <string.h> #include <algorithm> #include <stdio.h> #include &l

Codeforces Gym101341K:Competitions(DP)

http://codeforces.com/gym/101341/problem/K 题意:给出n个区间,每个区间有一个l, r, w,代表区间左端点右端点和区间的权值,现在可以选取一些区间,要求选择的区间不相交,问最大的权和可以是多少,如果权和相同,则选区间长度最短的.要要求输出区间个数和选了哪些区间. 思路:把区间按照右端点排序后,就可以维护从左往右,到p[i].r这个点的时候,已经选择的最大权和是多少,最小长度是多少,区间个数是多少. 因为可以二分找右端点小于等于当前区间的左端点的某个区间

Codeforces 988F Rain and Umbrellas(DP)

题目链接:http://codeforces.com/contest/988/problem/F 题目大意: 有三个整数a,n,m,a是终点坐标,给出n个范围(l,r)表示这块区域下雨,m把伞(p,w)在点p有重量为w的伞. 小明可以携带任意数量的伞,经过下雨处时必须要撑伞,小明每走一个单位长度消耗的体力与他所携带伞的重量相同, 求小明从0~a所需消耗的最少体力,若无解则输出-1. 解题思路: 第一种解法: 设dp[i]表示到达i点所需花费的最少体力,rain[i]表示第i段是否下雨(注意是段不

Codeforces Round #544 (Div. 3) dp + 双指针

https://codeforces.com/contest/1133/problem/E 题意 给你n个数(n<=5000),你需要对其挑选并进行分组,总组数不能超过k(k<=5000),每组数字差距不超过5,问最多能挑出多少数字 题解 先排序,在进行dp,定义dp[i][j]为前i个数分成j组的最大值 两个转移方向 不选 dp[i-1][j] -> dp[i][j] 和前面的分组 dp[lt[i]-1][j-1] -> dp[i][j] 怎么确定i前面的哪个点是最大的? 选择能

Educational Codeforces Round 63-D(基础DP)

题目链接:https://codeforces.com/contest/1155/problem/D 题意:给定n个数,可以选择一段连续子段将其乘x,也可以不操作,求最大连续子段和. 思路:比赛时觉得是dp,但怎么也想不出来QAQ,dp太难了...赛后看了别人题解,找到状态和转移方程就很简单了,然而比赛时我就是想不到... 考虑下标i:有3种情况,可能[0,i]都没有乘x,可能i乘了x,可能[i,n]都不会乘x.分别用dp[i][0]表示以i结尾的最长子段和且 [0,i]都没乘x,dp[i][1

http://codeforces.com/contest/575/problem/B

题目链接: http://codeforces.com/contest/575/problem/B 题解: 代码: #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn = 1e5 + 10; const int DEG = 22; const in

Codeforces 442B Andrey and Problem(贪心)

题目链接:Codeforces 442B Andrey and Problem 题目大意:Andrey有一个问题,想要朋友们为自己出一道题,现在他有n个朋友,每个朋友想出题目的概率为pi,但是他可以同时向多个人寻求帮助,不过他只能要一道题,也就是如果他向两个人寻求帮助,如果两个人都成功出题,也是不可以的. 解题思路:贪心,从概率最大的人开始考虑,如果询问他使得概率变大,则要询问. #include <cstdio> #include <cstring> #include <a

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