B1068 [SCOI2007]壓縮 區間dp
阿新 • • 發佈:2018-09-30
har ostream string border 我們 for using getchar() rip
這個題我狀態想對了,但是轉移錯了。。。dp的代碼難度都不大,但是思考含量太高了。。不會啊,我太菜了。
其實這個題就是一個正常的區間dp,中間多了一個特判的轉移就行了。
題幹:
Description
給一個由小寫字母組成的字符串,我們可以用一種簡單的方法來壓縮其中的重復信息。壓縮後的字符串除了小
寫字母外還可以(但不必)包含大寫字母R與M,其中M標記重復串的開始,R重復從上一個M(如果當前位置左邊沒
有M,則從串的開始算起)開始的解壓結果(稱為緩沖串)。 bcdcdcdcd可以壓縮為bMcdRR,下面是解壓縮的過程
另一個例子是abcabcdabcabcdxyxyz可以被壓縮為abcRdRMxyRz。
Input
輸入僅一行,包含待壓縮字符串,僅包含小寫字母,長度為n。
Output
輸出僅一行,即壓縮後字符串的最短長度。
Sample Input
bcdcdcdcdxcdcdcdcdSample Output
12HINT
在第一個例子中,解為aaaRa,在第二個例子中,解為bMcdRRxMcdRR。
【限制】
100%的數據滿足:1<=n<=50 100%的數據滿足:1<=n<=50
代碼:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < ‘0‘ || c > ‘9‘) if(c == ‘-‘) op = 1; x = c - ‘0‘; while(c = getchar(), c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar(‘-‘), x = -x; if(x >= 10) write(x / 10); putchar(‘0‘ + x % 10); } char s[100]; int n; int f[100][100][3]; bool check(int l,int r) { int mid = (l + r) >> 1; duke(i,1,mid - l + 1) { if(s[l + i - 1] != s[mid + i]) return 0; } return 1; } int main() { scanf("%s",s + 1); n = strlen(s + 1); lv(i,n,1) { duke(j,i,n) { f[i][j][0] = f[i][j][1] = j - i + 1; duke(k,i,j - 1) f[i][j][1] = min(f[i][j][1],min(f[i][k][0],f[i][k][1]) + 1 + min(f[k + 1][j][1],f[k + 1][j][0])); duke(k,i,j - 1) f[i][j][0] = min(f[i][j][0],f[i][k][0] + j - k); if((j - i + 1) % 2 == 0 && check(i,j)) f[i][j][0] = f[i][(i + j) / 2][0] + 1; } } printf("%d\n",min(f[1][n][0],f[1][n][1])); return 0; }
B1068 [SCOI2007]壓縮 區間dp