中文题。
可以想到当只有一个字符那么最少要添加1个,两个连续不相等的字符不需要添加。
可以设dp[i][j]代表从i到j最少需要添加几个。
分为两种情况:当 s[i] == s[j] 的时候,那么一定需要添加一个,可以在i的左边 也可以在j的右边,如果在i的左边加 那就是dp[i][j-1] + 1,添加的那个字符就是和s[j]相反的。
如果在j的右边加 那就是dp[i+1][j] + 1,添加的字符与s[i]相反。当然dp[i][j]取二者的较小值。
当s[i] != s[j]的时候,除了要算出以上的两种方案 还需要比较与 dp[i+1][j-1]的大小。
#include <algorithm> #include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #define MAX 0x3f3f3f3f #define N 2000 #define mod 1000000007 typedef long long LL; using namespace std; const double pi = acos(-1.0); int n; char s[N]; int dp[N][N], a[N]; int main() { int T; cin >> T; while(T--) { cin >> n >> s + 1; memset(a, 0, sizeof(a)); for(int i = 1; i <= n; i++) if(s[i] == '1') a[i] = 1; memset(dp, MAX, sizeof(dp)); for(int i = 1; i <= n; i++) dp[i][i] = 1, dp[i][i-1] = 0; // 注意初始化 dp[i][i-1] = 0; 也就是两个连续不相同的是不要添加字符的 WA了一次。。 for(int j = 2; j <= n; j++) { for(int i = j-1; i >= 1; i--) { dp[i][j] = min(dp[i+1][j], dp[i][j-1]) + 1; if(a[i] != a[j]) dp[i][j] = min(dp[i][j], dp[i+1][j-1]); } } cout << dp[1][n] << endl; } return 0; }
时间: 2024-08-28 08:11:41