【題意】
給定兩個長度相同的字串a,b。每次操作都能把a中的任意乙個子段變成相同的字元,問最少操作多少次a能變成b?
【思路】
dp[i][j]表示i-j區間內的最少次數
先操作第二個字串,我們先假設第i個字元的位置需要噴刷一次,對於所有的dp[i][j]=dp[i+1][j]+1、
在i-j區間內,如果有第k個跟第i個相同,那麼就可以將i-j區間借助k分成兩部分dp[i][j]=min(dp[i+1][k]+dp[k+1][j]);
處理完第2個字串後,我們就要看第乙個字串究竟需要噴刷多少次了,用ans[i]記錄0-i區間第二個字串得出的噴刷次數,如果第乙個字串的i位置與第二個字串的i位置相同,那麼這個位置就不用噴刷了,ans[i]=ans[i-1],如果不相同,就要就要借助乙個位於o-i區間內的變數來分割開。
對於dp[i][j] 來說最差的就是1+dp[i+1][j]咯,那怎麼減少呢。。。 如果(i,j]裡面也有個k使得b[i] == b[k]那麼得話, 可以刷[i,k]這麼長的一段,那麼就有可能減少1. 但是存在問題,如果有一段跨越了k怎麼辦。。。 嗯,這個問題是不會出現的, 因為在[i,k]刷了b[i].如果跨越了k那麼之前在b[k]刷的顏色就沒了,所以是不允許有跨段的, 所以要寫成&&想寫成 dp[i][j] = dp[i+1][k] + dp[k+1][j]。 為什麼不可以跨段 可以思考 brbr 。 然後後來的那個 一段 要麼是可以分段刷的,要麼是不可以分段刷的。-
先計算出空串塗成b串的代價,用dp[i][j]儲存區間[i, j]塗成和b串一樣的最小代價。
因為字元都不相同,那麼代價的優化點就在於b串中相同的字元。
dp[i][j] = min(dp[i+1][j]+1, dp[i+1][k]+dp[k+1][j]); (i+1<=k<=j && b[k] == b[i])
b[i]可以在塗區間[i+1, k]時順帶塗上。 處理時需要注意邊界。
整理我們已經有的資訊dp[i][j],把空串變成b[i] - b[j]的字串所需的最小代價。
設定ans[i]為a[0] - a[i]的字串變成b[0] - b[i]所需的最小代價。
則狀態轉移:
a[i] == b[i] ans[i] = ans[i-1];
a[i] != b[i] ans[i] = min(ans[i], ans[j] + dp[j+1][i]); 把區間[j+1, i]當做空串來處理。
例如zzzzzfzzzzz,長度為11,我們就將下標看做0~10
先將0~10刷一次,變成aaaaaaaaaaa
1~9刷一次,abbbbbbbbba
2~8:abcccccccba
3~7:abcdddddcba
4~6:abcdeeedcab
5:abcdefedcab
這樣就6次,變成了s2串了
第二個樣例也一樣
先將0~10刷一次,變成ccccccccccb
1~9刷一次,cdddddddddcb
2~8:cdcccccccdcb
3~7:cdcdddddcdcb
4~6:cdcdcccdcdcb
5:cdcdcdcdcdcb
最後竟串尾未處理的刷一次
就變成了串2cdcdcdcdcdcd
所以一共7次
【accepted】
1 #include2 #include3 #includeview code4 #include5 #include6 #include7
using
namespace
std;
8const
int maxn=1e5+20;9
const
int maxm=1e6;
10const
int inf=0x3f3f3f3f;11
12struct
edge
13edge[maxm];
16int
tol;
17int
head[maxn];
18int
gap[maxn],dep[maxn],pre[maxn],cur[maxn];
19int num[1200
];20
void
init()
2126
27void addedge(int u,int v,int w,int rw=0)28
4041
int sap(int start,int end,int
n)4261}
62for(int i=pre[u];i!=-1;i=pre[edge[i^1
].to])
6367 u=start;
68 ans+=min;
69continue;70
}71bool flag=false;72
intv;
73for(int i=cur[u];i!=-1;i=edge[i].next)
7482}83
if(flag)
8488
int min=n;
89for(int i=head[u];i!=-1;i=edge[i].next)
9096
}97 gap[dep[u]]--;
98if(!gap[dep[u]])
99102 dep[u]=min+1
;103 gap[dep[u]]++;
104if(u!=start)
105108
}109
return
ans;
110}
111int
a[maxn];
112int
n,m;
113int bit[11
];114
115int
main()
116122
while(~scanf("
%d%d
",&n,&m))
123136
}137 num[temp]++;
138}
139int people=-inf;
140for(int i=1024;i>=0;i--)
141147
}148
int planet=people+1
;149
for(int i=0;i<=1024;i++)
150155 addedge(0
,i,num[i]);
156for(int k=0;k)
157162
}163
}164
for(int i=planet;i)
165169
170if(num[0
])171
175int res=sap(0,planet+m,planet+m+1
);176
if(res==n)
177180
else
181184
getchar();
185}
186return
0;
187 }
codeforces 245H 區間DP 好題
方法一 先暴力求出每個字串是否是回文 列舉每個回文串的中間字元 儲存在dp i j 中 再從以求的小區間滾成大區間 view code include include char s 5005 int dp 5005 5005 int main for i 1 i len i 固定i,滾動j for ...
警衛安排(dp好題)
警衛安排 guard 題目描述 乙個重要的基地被分為 n 個連通的區域。出於某種神秘的原因,這些區域以乙個區域為核心,呈 一顆樹形分布。在每個區域安排警衛所需要的費用是不同的,而每個區域的警衛都可以望見其相鄰的區域,只要 乙個區域被乙個警衛望見或者是安排有警衛,這個區域就是安全的。你的任務是 在確保...
快餐問題(dp好題)
peter最近在r市開了一家快餐店,為了招攬顧客,該快餐店準備推出一種 該 由a個 漢堡,b個薯條和c個飲料組成。便宜。為了提高產量,peter從著名的麥當勞公司引進了n條 生產線。所有的生產線都可以生產漢堡,薯條和飲料,由於每條生產線每天所能提供的生產時間是有 限的 不同的,而漢堡,薯條和飲料的單...