注意这个求的是d[0][n-1]是前面的值。所以循环的时候i不能从0往后取,就是不能从前往后推。那样
d[0][n-1] 假如a[0]!=a[n-1]那么d[0][n-1] = min(d[1][n-1], d[0][n-2])这时候还没算过d[1][n-1]呢,而且后边N多状态都没算过呢,是不准确的。
应该从后往前推才行。就是求前面的值从后往前推
像递增子序列的问题,求的是d的最后的值,所以可以从前往后推。
还有如果i j相邻的话,比如8,9 那么d[i][j] = d[i+1][j-1]就是d[8][9]=d[9][8],恒等,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <utility>
char a[5000] = {0};
short int d[5000][5000];
using namespace std;
int main()
{
int n = 0;
freopen("in.text", "r", stdin);
scanf("%d", &n);
scanf("%s", a);
int i = 0;
int j = 0;
memset(d, 0, sizeof(d));
for (i = n-1; i >= 0; i--)
for (j = i+1; j < n; j++) {
if (a[i] == a[j]) {
d[i][j] = d[i+1][j-1];
}
else {
d[i][j] = min(d[i+1][j], d[i][j-1])+1;
}
}
printf("%d\n", d[0][n-1]);
}
用short勉强不超内存
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <utility>
char a[5000] = {0};
//short int d[5000][5000];
short int d[2][5000];
using namespace std;
int main()
{
int n = 0;
freopen("in.text", "r", stdin);
scanf("%d", &n);
scanf("%s", a);
int i = 0;
int j = 0;
memset(d, 0, sizeof(d));
for (i = n-1; i >= 0; i--)
for (j = i+1; j < n; j++) {
if (a[i] == a[j]) {
d[i&1][j] = d[(i+1)&1][j-1];
}
else {
d[i&1][j] = min(d[(i+1)&1][j], d[i&1][j-1])+1;
}
}
printf("%d\n", d[0][n-1]);
}
1159 | Accepted | 716K | 719MS | G++ | 755B | 2013-08-30 20:56:04 |
滚动数组