日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

动态规划训练10 [Coloring Brackets CodeForces - 149D]

發(fā)布時(shí)間:2023/12/3 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动态规划训练10 [Coloring Brackets CodeForces - 149D] 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

西安交大 軟件53 蔡少斐 整理

Coloring Brackets

?CodeForces - 149D?


題目大意:

給定合法的括號(hào)序列,讓你給括弧上色,并且上色時(shí)一定要滿足3個(gè)要求:

(1)每個(gè)括號(hào)要么被上紅色,要么被上藍(lán)色,要么不上色。

(2)一對(duì)匹配的左右括弧,有且只有其中的一個(gè)可以被上色。

(3)相鄰的括弧不能被涂上相同的顏色。


這道題也是很明顯的區(qū)間DP問題,遺憾的是,我一開始沒有想到怎么dp。


首先我們要進(jìn)行預(yù)處理,求出每個(gè)括號(hào)的唯一配對(duì)的括號(hào),即尋找他們一一對(duì)應(yīng)的關(guān)系,這個(gè)預(yù)處理很簡單,用棧操作一下就可以了

預(yù)處理代碼:

gets(str);stack<int> stk;int len = strlen(str);for(int i = 0;i < len;i++){if(str[i] == '('){stk.push(i);}else{int p = stk.top();stk.pop();mp[p] = i;mp[i] = p;}}

下面我們考慮的區(qū)間,全部都是配對(duì)合法的區(qū)間!

用一個(gè)四維數(shù)組dp[l][r][i][j]表示區(qū)間[l,r]且l處被涂上i色,r處被涂上j色。(規(guī)定無色為0,紅色為1,藍(lán)色為2)

那么我們可以得到下面的狀態(tài)轉(zhuǎn)移方程:

(1)當(dāng)區(qū)間長度只有2時(shí)候(兩個(gè)括弧一定是配對(duì)的,因?yàn)槲覀兛紤]的所有區(qū)間都是配對(duì)合法的區(qū)間),上色方案是非常好確定的。

dp[l][r][0][1] = 1;
dp[l][r][0][2] = 1;
dp[l][r][1][0] = 1;
dp[l][r][2][0] = 1;

(2)當(dāng)區(qū)間的左右括弧是配對(duì)的時(shí)候(判斷左右括弧是否匹配,用到了預(yù)處理得到的結(jié)果)。則有如下轉(zhuǎn)移方法:

if(j != 1)
dp[l][r][0][1] = (dp[l][r][0][1] + dp[l+1][r-1][i][j])%MOD;
if(j != 2)
dp[l][r][0][2] = (dp[l][r][0][2] + dp[l+1][r-1][i][j])%MOD;
if(i != 1)
dp[l][r][1][0] = (dp[l][r][1][0] + dp[l+1][r-1][i][j])%MOD;
if(i != 2)
dp[l][r][2][0] = (dp[l][r][2][0] + dp[l+1][r-1][i][j])%MOD;

(3)當(dāng)區(qū)間非左右配對(duì)時(shí),把區(qū)間劃分為左右兩個(gè)各自合法 的區(qū)間,轉(zhuǎn)移方程是。

dp[l][r][i][j] = (dp[l][r][i][j] + dp[l][k][i][p] * dp[k+1][r][q][j]%MOD)%MOD;

這里注意k代表的是與l配對(duì)的括號(hào),那么k+1就是與r配對(duì)的括號(hào)了。(這就是預(yù)處理的作用!)


而在動(dòng)態(tài)規(guī)劃的實(shí)現(xiàn)過程中,我們發(fā)現(xiàn)并非所有的區(qū)間都是合法的,只有少部分的區(qū)間是合法的,因此我們用自頂向下的記憶化dp的方法,這樣可以簡化代碼的實(shí)現(xiàn)。


代碼:

#include <iostream> #include <cstdio> #include <cstring> #include <stack> #include <algorithm> #define int long long using namespace std; const int MAX = 705; const int MOD = 1e9 + 7; int used[MAX][MAX]; int mp[MAX]; char str[MAX]; int dp[MAX][MAX][3][3]; void dfs(int l,int r){if(used[l][r]) return ;used[l][r] = 1;if(l + 1 == r){dp[l][r][0][1] = 1;dp[l][r][0][2] = 1;dp[l][r][1][0] = 1;dp[l][r][2][0] = 1;return ;}if(mp[l] == r){//配對(duì)的情況 dfs(l+1,r-1);for(int i = 0;i < 3;i++){for(int j = 0;j < 3;j++){if(j != 1)dp[l][r][0][1] = (dp[l][r][0][1] + dp[l+1][r-1][i][j])%MOD;if(j != 2)dp[l][r][0][2] = (dp[l][r][0][2] + dp[l+1][r-1][i][j])%MOD;if(i != 1)dp[l][r][1][0] = (dp[l][r][1][0] + dp[l+1][r-1][i][j])%MOD; if(i != 2)dp[l][r][2][0] = (dp[l][r][2][0] + dp[l+1][r-1][i][j])%MOD; }}}else{int k = mp[l];dfs(l,k);dfs(k+1,r);for(int i = 0;i < 3;i++){for(int j = 0;j < 3;j++){for(int p = 0;p < 3;p++){for(int q = 0;q < 3;q++){if(p + q == 0 || p != q ){dp[l][r][i][j] = (dp[l][r][i][j] + dp[l][k][i][p] * dp[k+1][r][q][j]%MOD)%MOD;}}} }} } } main(){gets(str);stack<int> stk;int len = strlen(str);for(int i = 0;i < len;i++){if(str[i] == '('){stk.push(i);}else{int p = stk.top();stk.pop();mp[p] = i;mp[i] = p;}}dfs(0,len-1);int ans = 0;for(int i = 0;i < 3;i++){for(int j = 0;j < 3;j++){ans = (ans + dp[0][len-1][i][j])%MOD;}}cout<<ans<<endl;return 0; }

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的动态规划训练10 [Coloring Brackets CodeForces - 149D]的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。