2

ACM任务

ACM任务

 

【问题描述】

        萨格勒布大学、伊万大学和古斯塔夫大学的团队正在摩洛哥参加ACM国际大学生程序设计大赛的世界总决赛。他们的技术指导教练Goran提出了一个对付总决赛的无敌策略
        开始,每个团队成员很快预估出N个任务的难度。这些难度用数字1到5来表示,其含义如下:
        1 呵呵呵
        2 来吧!
        3 OK没问题。
        4 嗯……
        5 你疯了吗?
       之后,他们将分配他们之间的任务。为了简单起见,这些任务将被分成三部分,每个团队的成员将获得一个非空的连续任务数组。分配的目的是使所估计的难度总和最小。你的任务是计算最小可能的总和。
 

【输入格式】

第一行输入一个整数N,表示任务的数量。
接下来的三行每行包含N个整数(这些数的范围是[1,5]之间的整数),分别给出每个团队估计的任务难度。第一行对应于萨格勒布大学团队的估计难度,第二行是伊万大学,第三行是古斯塔夫大学。
 

【输出格式】

输出共一行一个整数,即最小的难度总和。
 

【样例输入】

3
1 3 3
1 1 1
1 2 3
 

【样例输出】

4

【算法分析】

这是一道DP题,我们可以把问题拆分开解决,将三所大学先降维成两所,那么我们只需要枚举n个任务分配的一个分割点即可,解决后将两所大学合并成一所再与第三所进行同样的操作。可用f[i][j]代表将前i个任务分配给i+1个人时的难度最小值,由此可推得状态转移方程为
if(i>=2)f[i][1]=min(f[i-1][0],f[i-1][1])+a[num[x][1]][i];//当i>=2时,任务才够分给两个人,这句所求的是将i个任务分给两个人的最优解
//即为将i-1个任务分给1个人的最优解和将i-1个任务分给2个人的最优解的最小值加上对于第num[x][1]所大学来说第i个任务的难度,其中num数组表示每个大学的做任务的顺序 if(i>=3)f[i][2]=min(f[i-1][1],f[i-1][2])+a[num[x][2]][i];//和上面差不多,就不赘述了;

  

【AC代码】

 
#include<bits/stdc++.h>
#define For(i,l,r) for(int i=(l);i<=(r);i++)
using namespace std;
int num[6][3]= {{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,0,1},{2,1,0}};
int n,ans=0x3f3f3f3f,a[3][150010],f[150010][3];
int main() {
    cin>>n;
    For(i,0,2) For(j,1,n) cin>>a[i][j];
    For(x,0,5) {
        memset(f,63,sizeof(f));
        f[0][0]=0;
        For(i,1,n) {
            f[i][0]=f[i-1][0]+a[num[x][0]][i];
            if(i>=2) f[i][1]=min(f[i-1][0],f[i-1][1])+a[num[x][1]][i];
            if(i>=3) f[i][2]=min(f[i-1][1],f[i-1][2])+a[num[x][2]][i];
        }
        ans=min(ans,f[n][2]);
    }
    cout<<ans;
}

 

posted @ 2021-12-05 11:17  彧。  阅读(75)  评论(0编辑  收藏  举报