题意:有一个字符串上有‘-’和'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;
}