题解 - CF706C

动态规划吧,不难,被坑了一下,一定不要直接用memset给dp赋0X7F,因为memset按位初始化,所以可能导致有的地方数值不够大。
好吧,我几乎不懂。。。可以的话去学一下memset赋值原理吧。

/*
对于正解状态,第dp[i][0/1]分别表示到达第i个位置时的最少energy。If both dp[i][0] and dp[i][1] 对应的字符串都比dp[i+1][0/1]的要大,则输出-1。
dp[i][0]表示不旋转,dp[i][1]表示旋转。
dp[i][0] = min(dp[i-1][0],dp[i-1][1]) + c[i](if(check(dp[i-1][0/1] both == true)//It's Wrong.
同理可得dp[i][1]。 
*/
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
#define MAXN 100010
#define INF 1e18
//注意INF不可以用0X7F!!!0X7F对于memset虽然够大(因为memste是用按字节赋值的。。。)
int n;
long long eng[MAXN],dp[MAXN][2];
string str[MAXN];
bool check(int a, bool x,bool y)
{//用于比较编号为a-1的字符串在X状态下是否比编号为a的字符串在y状态下要小。 
	int i = 0;
	string stra = str[a-1],strb = str[a];
	if(x)reverse(stra.begin(),stra.end());
	if(y)reverse(strb.begin(),strb.end());
	
	//while(stra[i] == strb[i] && i <= min(stra.length(),strb.length()))i++;
//	cout << strb[i] << " " << stra[i] << endl;
	if(strb >= stra)return 1;
	return 0;
}
int main()
{
	cin >> n;
	for(int i = 1; i <= n; ++i)cin >> eng[i];
	for(int i = 1; i <= n; ++i)cin >> str[i]; 
	for(int i = 1; i <= n; ++i)dp[i][0] = dp[i][1] = INF; 
	bool flag = 0;
	dp[1][0] = 0,dp[1][1] = eng[1];
	 for(int i = 2; i <= n; ++i)
	 {
	 	flag = 0;
	 	if(check(i,0,0) && dp[i-1][0] != INF)dp[i][0] = dp[i-1][0],flag = 1;
	 	if(check(i,0,1) && dp[i-1][0] != INF)dp[i][1] = dp[i-1][0] + eng[i],flag = 1;
	 	if(check(i,1,0) && dp[i-1][1] != INF)dp[i][0] = min(dp[i][0],dp[i-1][1]),flag = 1;
	 	if(check(i,1,1) && dp[i-1][1] != INF)dp[i][1] = min(dp[i][1],dp[i-1][1] + eng[i]),flag = 1;
	 	
	 	if(!flag){cout << -1 << endl;return 0;}
	 }
//	 cout << (check(2,0,0) && dp[1][0] != INF) << endl;
	//字符串比较 ,abc<abcd acb > abcd 
	//for(int i = 1; i <= n; ++i)cout << dp[i][0] << " " << dp[i][1] << endl;
	cout << min(dp[n][0],dp[n][1]) << endl;
	return 0;
 }

posted @ 2021-12-12 11:48  边缘坐标  阅读(75)  评论(0编辑  收藏  举报
-->