1. 程式人生 > >[CQOI2007]塗色

[CQOI2007]塗色

ide %s tar 就是 技術 scanf ack std mem

嘟嘟嘟

區間dp。

令dp[i][j]表示從[i, j]的最少染色方案數。

很明顯,當 i == j 時,dp[i][j] = 1;否則,如果s[i] == s[j],即兩個端點顏色相同,那麽端點處的顏色只用染一次,也就是說可以從 i 這頭染,也可以從 j 這頭染,則dp[i][j] = min(dp[i +1][j], dp[i][j - 1]);如果s[i] != s[j],那麽我們將[i, j]分兩半染色,然後枚舉斷點k,則dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j]),這為什麽一定對呢,舉個例子:比如[i, j]為RGGBE,斷點枚舉到RG GBE,此時dp[i][k] + dp[k + 1][j]等於5,然而最優應該是4,不過4的情況是在RGG BE時就得到的,所以dp[i][j]一定能從dp[i][k]和dp[k + 1][j]得到。

技術分享圖片
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<vector>
 8 #include<queue>
 9 #include<stack>
10 #include<cctype>
11 using namespace std;
12 #define
enter puts("") 13 #define space putchar(‘ ‘) 14 #define Mem(a) memset(a, 0, sizeof(a)) 15 typedef long long ll; 16 typedef double db; 17 const int INF = 0x3f3f3f3f; 18 const db eps = 1e-8; 19 const int maxn = 55; 20 inline ll read() 21 { 22 ll ans = 0; 23 char ch = getchar(), last = ; 24 while
(!isdigit(ch)) last = ch, ch = getchar(); 25 while(isdigit(ch)) ans = (ans << 3) + (ans << 1) + ch - 0, ch = getchar(); 26 if(last == -) ans = -ans; 27 return ans; 28 } 29 inline void write(ll x) 30 { 31 if(x < 0) putchar(-), x = -x; 32 if(x >= 10) write(x / 10); 33 putchar(x % 10 + 0); 34 } 35 36 char s[maxn]; 37 int dp[maxn][maxn]; 38 39 int main() 40 { 41 scanf("%s", s + 1); 42 int n = strlen(s + 1); 43 for(int L = 1; L <= n; ++L) 44 for(int i = 1; i + L - 1 <= n; ++i) 45 for(int j = i; j - i + 1 <= L; ++j) 46 { 47 dp[i][j] = INF; //別忘了 48 if(i == j) dp[i][j] = 1; 49 else if(s[i] == s[j]) dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]); 50 else for(int k = i; k <= j; ++k) 51 dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j]); 52 } 53 write(dp[1][n]); enter; 54 return 0; 55 }
View Code

[CQOI2007]塗色