36ptsdp求调
查看原帖
36ptsdp求调
481337
Pratty楼主2024/10/14 20:24

代码底部有我的见解。

#include <bits/stdc++.h>
#define int long long
using namespace std;
int c, t, v[15], ans, flag[110000], tot, num[10], vis[10];
pair<int, int> dp[110000][10];
string s;
signed main() {
	scanf("%lld", &c);
	scanf("%lld", &t);
	while (t--) {
		ans = 0;
		cin >> s;
		s = " " + s;
		for (int i = 1; i <= 9; i++) {
			scanf("%lld", &v[i]);
		}
		int len = (int)s.size() - 1;
		for (int i = 0; i <= len; i++) {
			for (int j = 0; j <= 6; j++) {
				dp[i][j].first = 0;
				dp[i][j].second = 0;
				dp[0][j+1].second=-1e18;
			}
			flag[i] = 1;
		}
/*0
5
111222333445
300 900 222 300 2000 193 283 298 3093 333
0
19
2384233477373626363647398326
1239 8213 2731 2938 37321 37828 283 281 3823*/
		for (int i = 1; i <= len; i++) {
			for (int j = 0; j <= 6; j++) {
				dp[i][j] = dp[i-1][j];
				if (j && dp[i][j].second < dp[i-1][j-1].second+v[s[i]-'0']-(dp[i-1][j-1].first*10+s[i]-'0')+dp[i-1][j-1].first) {
					dp[i][j].second = dp[i-1][j-1].second+v[s[i]-'0']-(dp[i-1][j-1].first*10+s[i]-'0')+dp[i-1][j-1].first;
					dp[i][j].first = dp[i-1][j-1].first*10+s[i]-'0';
				}
//				cout << i << ' ' << j << ' ' << dp[i][j].first << ' ' << dp[i][j].second << endl;
			}
		}
		int mx = 0, shu = -1, Ans = 0;
		for (int i = 1; i <= 6; i++) {
//			cout << dp[len][i].second << endl;
			if (mx < dp[len][i].second) {
				shu = dp[len][i].first;
				mx = dp[len][i].second;
			}
		}
//		cout << shu << endl;
		tot = 0;
		if (shu != -1) {
			while (shu) {
				num[++tot] = shu % 10;
				shu /= 10;
			}
			for (int i = 1; i <= tot; i++) {
				vis[i] = 0;
			}
			for (int i = 1; i <= len; i++) {
				for (int j = 1; j <= tot; j++) {
					if (s[i] - '0' == num[j] && !vis[j] && flag[i]) {
						flag[i] = 0;
						vis[j] = 1;
						Ans += v[s[i] - '0'];
					}
				}
			}
			Ans = Ans - mx;
		}
//		cout << Ans << endl;
		for (int i = 1; i <= len; i++) {
			if (flag[i]) {
//				cout << v[s[i] - '0'] << ';';
				ans += v[s[i] - '0'];
			}
		}
//		cout << endl;
		printf("%lld\n", ans + Ans);
//		return 0;
	}
	return 0;
} 
/*
求一个子序列,使(子序列中v[s[i]-'0']的和-子序列这个数)最大(v<=100000) 
如果是正的,就用,是负的,就不用 
易得这个子序列的长度至多为 6,
设dp[i][j]表示i为止的子序列,已选j个数的(总数,最大差值)
nd=dp[i-1][j-1].second+v[s[i]-'0']-dp[i-1][j-1].first*10+s[i]-'0'
dp[i][j] = max(dp[i-1][j], nd) 
*/


2024/10/14 20:24
加载中...