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)
BZOJ1806: [Ioi2007]Miners 矿工配餐