静态网页模板怎么用湖南百度seo排名点击软件
题意:给一串字符串,从A-E,数值大小分别为1,10,100,1000,10000,对于这个字符串数值总和的计算方式是,如果那一位的字符的右侧有严格大于它的字符,那么数值变为负数,有一次随意改写一个位置字符的操作,问最大的数值是多少。
dp思路:
1.首先由于题目的性质,改变一个位置的字符,不会对它的右侧造成影响,所以在已知右侧字符的情况下,左侧其实要关注的是已知字符子串的最大,因为大于最大不会受影响,小于怎么样都受影响,只需要关注已知出现的最大字符,这给了dp的机会,所以首先反转字符串
2.反转字符串在于,现在问题就转化成了,已知左边字符串的情况,问右边在后续的最大数值,因为前面不会受后面影响,所以这就能dp了。
那么已知左侧,其实只要关注最大,上面解释过了,dp数组此时很明显dp[i][j][k],代表当进行到第i位,出现过的最大字符(j),然后操作过k次(k被限定为0/1)即可,然后就是正常dp。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
const int N = 3e5+10;
const int INF = 1e18;
const int MOD = 1e9+7;int cnum[5]={1,10,100,1000,10000};
int dp[N][5][2];void solve(){string s;cin >> s;s=" "+s;reverse(s.begin()+1,s.end());int n=s.size();for(int i=0;i<=n;i++){for(int j=0;j<5;j++){for(int k=0;k<2;k++){dp[i][j][k]=-INF;}}}dp[0][0][0]=0;for(int i=1;i<n;i++){for(int j=0;j<5;j++){for(int k=0;k<2;k++){if(j>(s[i]-'A')){dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k]-cnum[s[i]-'A']);}else{dp[i][s[i]-'A'][k]=max(dp[i][s[i]-'A'][k],dp[i-1][j][k]+cnum[s[i]-'A']);}}for(int k=0;k<5;k++){if(j>k){dp[i][j][1]=max(dp[i][j][1],dp[i-1][j][0]-cnum[k]);}else{dp[i][k][1]=max(dp[i][k][1],dp[i-1][j][0]+cnum[k]);}}}}int res=-INF;for(int i=0;i<5;i++){res=max(res,dp[n-1][i][0]);res=max(res,dp[n-1][i][1]);}cout << res << endl;}signed main() {IOS;int t = 1;cin >> t;while (t--) {solve();}}
非常简洁明了的代码,感觉比自己写的强了几百倍,自己写的时候不仅方向错误,而且后面看了思路,实现的也不好。