http://poj.org/problem?id=1159
Description
Input
Output
Sample Input
5 Ab3bd
Sample Output
2
Source
#include <iostream> using namespace std; const short N = 5001; short m[N][N]; short foo(char* str,short left,short right) { if(left == right) { return m[left][right] = 0; } else if( left + 1 == right ) { if( str[left] == str[right] ) { return m[left][right] = 0; } else { return m[left][right] = 1; } } else { if( m[left][right] != -1 ) { return m[left][right]; } else { if(str[left] == str[right]) { return m[left][right] = foo(str,left + 1, right - 1); } else { short a = foo(str,left, right - 1) + 1; short b = foo(str,left + 1, right) + 1; return m[left][right] = a < b ? a : b; } } } } int main(int argc, char** argv) { char str[N]; short i, j, n; for( i = 0; i < N; ++i) { for(j =0; j < N; ++j) { m[i][j] = -1; } } cin>>n; i = 0; while(i < n) { cin>>str[i++]; } str[i]=0; cout<<foo(str,0,n - 1); return 0; }
本来二维数组m[N][N]是int型的,但是OJ报告内存超过限制,转用short即可,可以覆盖5000,因为题目要求是 2<N<5001,或者可以使用滚动数组,可以看如下的另一个代码。
#include <iostream> #include <cstring> using namespace std; const int N = 5001; short m[2][N]; short foo(char* str, short n) { short i, j, k, k1, k2, a, b; for(k = 1; k < n; ++k) { k1 = k & 1; k2 = (k - 1) & 1; for(i = 0; i + k < n; ++i) { j = i + k; if(str[i] == str[j]) { m[k1][i] = m[k1][i+1]; } else { m[k1][i] = 1 + (m[k2][i] < m[k2][i+1] ? m[k2][i] : m[k2][i+1]); } } } return m[(n-1)&1][0]; } int main(int argc, char** argv) { char str[N]; short i, n; i = 0; cin>>n; while(i < n) { cin>>str[i++]; } str[i]=0; cout<<foo(str,n); return 0; }
在这里用到一个滚动数组,妙用了&1,就是轮换使用两个一维数组,降低了一个数量级的空间复杂度。
写一次代码就有些心得体会,看来算法还是得通过实现来巩固掌握。
本文基于知识共享署名-非商业性使用 3.0 许可协议进行许可。欢迎转载、演绎,但是必须保留本文的署名林羽飞扬,若需咨询,请给我发信