A bottom-up DP. To be honest, it is not easy to relate DP to this problem. Maybe, all "most""least" problems can be solved using DP..
Reference: http://blog.sina.com.cn/s/blog_8e6023de01014ptz.html
There's an important details to AC: in case of "())", there are 2 solutions: ()() and (()). For the AC code, the former one is preferred.
// 1141 // http://blog.sina.com.cn/s/blog_8e6023de01014ptz.html // #include <stdio.h> #include <string.h> #include <memory.h> #define MAX_LEN 101 bool isMatched(char *in, int i, int j) { return (in[i] == '(' && in[j] == ')') || (in[i] == '[' && in[j] == ']'); } void printPath(int path[MAX_LEN][MAX_LEN], int i, int j, char in[MAX_LEN]) { int sInx = path[i][j]; if (sInx == -1) { if (i == j) { //printf("Complete @ %d ", i); switch (in[i]) { case '(': case ')': printf("()"); break; case '[': case ']': printf("[]"); break; } return; } else if (i + 1 == j) { //printf("Already matched: [%d, %d] ", i, j); printf("%c%c", in[i], in[j]); return; } else if ((i+1) < j) { printf("%c", in[i]); printPath(path, i + 1, j - 1, in); printf("%c", in[j]); } } else { printPath(path, 0, path[i][j], in); //printf("Break @ %d ", path[i][j], in); printPath(path, path[i][j] + 1, j, in); } } void calc(char in[MAX_LEN]) { unsigned slen = strlen(in); if (slen == 0) { printf(" "); return; } else if (slen > 0) { int dp[MAX_LEN][MAX_LEN]; int path[MAX_LEN][MAX_LEN]; // Init for (int i = 0; i < MAX_LEN; i ++) for (int j = 0; j < MAX_LEN; j++) { dp[i][j] = 0xFFFFFF; path[i][j] = -1; } // Def: dp[i][j] = min num of chars to add, from i to j // Recurrence relation: // 1. dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j]), where k in (i..j) // 2. dp[i][j] = dp[i+1][j-1], <IF in[i]:in[j] = [] or ()> // i..j is range, k is interval for (int k = 0; k < slen; k++) // NOTE: this is a bottom-up DP. We have to go from 0 to slen as interval for (int i = 0, j = i + k; i < slen - k; i ++, j ++) { if (i == j) { dp[i][j] = 1; path[i][j] = -1; continue; } bool bIsMatched = isMatched(in, i, j); if (bIsMatched) // eq 2 { if (k == 1) // length == 2 { dp[i][j] = 0; path[i][j] = -1; continue; } else if (k > 1) // length > 2 { dp[i][j] = dp[i + 1][j - 1]; path[i][j] = -1; // we don't split matched pair // A: we still go ahead with eq1 } } //else // eq1 { // t is iterator of split index for (int t = i; t < j; t++) { int newVal = dp[i][t] + dp[t + 1][j]; if (newVal <= dp[i][j]) // Label A: we prefer splitted solution { dp[i][j] = newVal; path[i][j] = t; } } } } printPath(path, 0, slen - 1, in); } // if (slen > 0) } int main() { char in[MAX_LEN] = { 0 }; gets(in); calc(in); printf(" "); return 0; }