题意:有一个字符串上有‘-’和'o'字符,如果两个连续的'o'的左边是'-',那么可以让左边的'o'变成‘-',而两个连续的'o'变成'-',右边类似,问怎样变化可以让字符串最后剩余的'o'最少,输出最后'o'的个数。

题解:每种状态对应不同的字符串,如果一个字符串此时可以最多剩余n个'o',而经过一次移动会使此时'o'最多减少数量减一,那么状态转移方程可列为f[s] = max{f[s], f[s1] + 1},f就是一个map存字符串状态,key就是此时最多减少的'o'的数量,因为左移或右移,要分两种情况。

#include <stdio.h>
#include <string>
#include <map>
#include <iostream>
using namespace std;
const int N = 15;

map<string, int> f;
string str;
int n;

int dp(string s) {
	if (f[s] != 0)
		return f[s];
	string temp;
	for (int i = 0; i < 10; i++) {
		if (s[i] == 'o' && s[i + 1] == 'o' && s[i + 2] == '-') {
			temp = s;
			temp[i] = temp[i + 1] = '-';
			temp[i + 2] = 'o';
			int temp2 = dp(temp) + 1;
			f[s] = f[s] > temp2 ? f[s] : temp2;
		}
	}
	for (int i = 0; i < 10; i++) {
		if (s[i] == '-' && s[i + 1] == 'o' && s[i + 2] == 'o') {
			temp = s;
			temp[i] = 'o';
			temp[i + 1] = temp[i + 2] = '-';
			int temp2 = dp(temp) + 1;
			f[s] = f[s] > temp2 ? f[s] : temp2;
		}
	}
	return f[s];
}

int main() {
	scanf("%d", &n);
	while (n--) {
		cin >> str;
		int num = 0;
		f.clear();
		for (int i = 0; i < N; i++)
			if (str[i] == 'o')
				num++;
		printf("%d\n", num - dp(str));
	}
	return 0;
}