山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

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 }

 

posted on 2016-04-02 16:55  hahalidaxin  阅读(350)  评论(0编辑  收藏  举报