bzoj 1806 [Ioi2007]Miners 矿工配餐(DP)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1806 [Ioi2007]Miners 矿工配餐(DP)相关的知识,希望对你有一定的参考价值。
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=1806
【题意】
给定一个权在1..3内的序列,在保持相对位置不变的情况下拆分成两个序列,使获益最大。
【思路】
设f[i][a][b][c][d]表示前i个数,分给A的倒数两个为ab,分给B的倒数两个为cd,则有转移式:
f[i+1][b][x][c][d]<- f[i][a][b][c][d]+w(a,b,x)
f[i+1][a][b][d][x]<- f[i][a][b][c][d]+w(c,d,x)
其中x=s[i],w为权值计算函数。
【代码】
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #define FOR(a,b,c) for(int a=b;a<=c;a++) 5 using namespace std; 6 7 const int N = 1e5+5; 8 9 char s[N]; 10 int n,f[2][4][4][4][4]; 11 12 int calc(int a,int b,int x) 13 { 14 int s=1; 15 if(a) s++; if(b) s++; 16 if(a==b&&a) s--; 17 if(x==a) s--; 18 if(x==b&&a!=b) s--; 19 return s; 20 } 21 22 int main() 23 { 24 scanf("%d%s",&n,s+1); 25 int cur=0; 26 memset(f[cur],0xef,sizeof(f[cur])); 27 f[cur][0][0][0][0]=0; 28 FOR(i,1,n) { 29 cur^=1; 30 int x; 31 if(s[i]==‘M‘) x=1; else if(s[i]==‘F‘) x=2; else x=3; 32 memset(f[cur],0xef,sizeof(f[cur])); 33 FOR(a,0,3) FOR(b,0,3) FOR(c,0,3) FOR(d,0,3) { 34 f[cur][b][x][c][d]=max(f[cur][b][x][c][d],f[cur^1][a][b][c][d]+calc(a,b,x)); 35 f[cur][a][b][d][x]=max(f[cur][a][b][d][x],f[cur^1][a][b][c][d]+calc(c,d,x)); 36 } 37 } 38 int ans=0; 39 FOR(a,0,3) FOR(b,0,3) FOR(c,0,3) FOR(d,0,3) 40 ans=max(ans,f[cur][a][b][c][d]); 41 printf("%d\n",ans); 42 return 0; 43 }
以上是关于bzoj 1806 [Ioi2007]Miners 矿工配餐(DP)的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ1806: [Ioi2007]Miners 矿工配餐