Vijos1386 IOI2007 矿工配餐 动态规划

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vijos1386 IOI2007 矿工配餐 动态规划相关的知识,希望对你有一定的参考价值。

感觉早些年IOI的题都不难啊,也就NOIp难度……现在貌似变难了

状态用dp[n][a1][b1][a2][b2]表示

n表示处理到前n个餐车

第一组矿工得到的最近一种食物用a1表示,a1的上一种食物用b1表示,第二组矿工的用a2和b2表示

a和b的取值范围为[0,3],0表示没有食物,1~3分别表示三种食物中的一种

第一维可以用滚动数组优化空间

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 const int maxN=100001;
 6 
 7 int dp[2][4][4][4][4];
 8 //none=0,bread=1,meat=2,fish=3
 9 int N;
10 char seq[maxN];
11 int s[maxN];
12 
13 inline int code(char x)
14 {
15     switch(x)
16     {
17     case B : return 1;
18     case M : return 2;
19     case F : return 3;
20     }
21     return 0; //unused
22 }
23 
24 void input()
25 {
26     scanf("%d",&N);
27     scanf("%s",seq);
28     for(int i=0;i<N;i++) s[i]=code(seq[i]);
29 }
30 
31 inline int val(int cur,int last1,int last2)
32 {
33     if(last2==0) return (cur==last1)?1:2;
34     else if(cur==last1) return (last1==last2)?1:2;
35     else return (last1==last2 || cur==last2)?2:3;
36 }
37 
38 int solve()
39 {
40     memset(dp[0],0xe0,sizeof(dp[0]));
41     dp[0][s[0]][0][0][0]=dp[0][0][0][s[0]][0]=1;
42     for(int i=1;i<N;i++)
43     {
44         int& v=s[i];
45         memset(dp[1],0xe0,sizeof(dp[1]));
46         for(int a1=0;a1<4;a1++)
47         {
48             if(!a1) { //b1=0
49                 for(int a2=1;a2<4;a2++)
50                     for(int b2=0;b2<4;b2++) {
51                         dp[1][v][0][a2][b2]=std::max
52                                 (dp[1][v][0][a2][b2],
53                                 dp[0][0][0][a2][b2]+1);
54                         dp[1][0][0][v][a2]=std::max
55                                 (dp[1][0][0][v][a2],
56                                 dp[0][0][0][a2][b2]+val(v,a2,b2));
57                     }
58             }
59             else for(int b1=0;b1<4;b1++)
60                 for(int a2=0;a2<4;a2++)
61                 {
62                     if(!a2) {
63                         dp[1][a1][b1][v][0]=std::max
64                                 (dp[1][a1][b1][v][0],
65                                 dp[0][a1][b1][0][0]+1);
66                         dp[1][v][a1][0][0]=std::max
67                                 (dp[1][v][a1][0][0],
68                                 dp[0][a1][b1][0][0]+val(v,a1,b1));
69                     }
70                     else for(int b2=0;b2<4;b2++) {
71                         dp[1][v][a1][a2][b2]=std::max
72                                 (dp[1][v][a1][a2][b2],
73                                  dp[0][a1][b1][a2][b2]+val(v,a1,b1));
74                         dp[1][a1][b1][v][a2]=std::max
75                                 (dp[1][a1][b1][v][a2],
76                                  dp[0][a1][b1][a2][b2]+val(v,a2,b2));
77                     }
78                 }
79         }
80         memcpy(dp[0],dp[1],sizeof(dp[1]));
81     }
82     int ans=-1;
83     for(int a1=0;a1<4;a1++)
84         for(int b1=0;b1<4;b1++)
85             for(int a2=0;a2<4;a2++)
86                 for(int b2=0;b2<4;b2++)
87                     ans=std::max(ans,dp[0][a1][b1][a2][b2]);
88     return ans;
89 }
90 
91 int main()
92 {
93     input();
94     printf("%d\n",solve());
95     return 0;
96 }

 

以上是关于Vijos1386 IOI2007 矿工配餐 动态规划的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1806[Ioi2007]Miners 矿工配餐 DP

bzoj 1806 [Ioi2007]Miners 矿工配餐(DP)

矿工配餐_IOI2007Miners

BZOJ1806: [Ioi2007]Miners 矿工配餐

bzoj1806[Ioi2007]Miners 矿工配餐 dp

bzoj1806