• 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
    ",ans);
    42     return 0;
    43 }
  • 相关阅读:
    scott登录查询常用语句
    Oracle服务端及客户端安装
    SVN简单使用
    dos命令--查询进程
    第二周学习总结
    第一周学习总结
    虚拟机安装教程及网络连接方式的解释
    两天学习总结
    方差
    thinkphp 总结 转
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5347804.html
Copyright © 2020-2023  润新知