洛谷 1130_红pai_dp

发布于 2019-05-13  887 次阅读


题目描述

某地临时居民想获得长期居住权就必须申请拿到红牌。获得红牌的过程是相当复杂 ,一共包括N个步骤。每一步骤都由政府的某个工作人员负责检查你所提交的材料是否符合条件。为了加快进程,每一步政府都派了M个工作人员来检查材料。不幸的是,并不是每一个工作人员效率都很高。尽管如此,为了体现“公开政府”的政策,政府部门把每一个工作人员的处理一个申请所花天数都对外界公开。

为了防止所有申请人都到效率高的工作人员去申请。这M*N个工作人员被分成M个小组。每一组在每一步都有一个工作人员。申请人可以选择任意一个小组也可以更换小组。但是更换小组是很严格的,一定要相邻两个步骤之间来更换,而不能在某一步骤已经开始但还没结束的时候提出更换,并且也只能从原来的小组I更换到小组I+1,当然从小组M可以更换到小组1。对更换小组的次数没有限制。

例如:下面是3个小组,每个小组4个步骤工作天数:

小组1 2 6 1 8

小组2 3 6 2 6

小组3 4 2 3 6

例子中,可以选择小组1来完成整个过程一共花了2+6+1+8=17天,也可以从小组2开始第一步,然后第二步更换到小组3,第三步到小组1,第四步再到小组2,这样一共花了3+2+1+6=12天。你可以发现没有比这样效率更高的选择。

你的任务是求出完成申请所花最少天数。


思路

用f[j][i]表示当前最小值
f[j][i]+=min(f[j][i-1],f[j-1][i-1])
O(nm)

#include <stdio.h>
int a[3000][3000];
int min(int x,int y)
{
    return x<y?x:y;
}
int main()
{
    int n,m;
    scanf("%d%d",&m,&n);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            scanf("%d",&a[i][j]);

    for (int i=1;i<=m;i++)
    {
        a[0][i]=a[n][i];
    }
    for (int i=2;i<=m;i++)
    {
        for (int j=1;j<=n;j++)
           a[j][i]+=min(a[j][i-1],a[j-1][i-1]);
       a[0][i]=a[n][i];
    }
    int ans=0x7fffffff;
    for (int i=1;i<=n;i++)
        ans=min(ans,a[i][m]);
    printf("%d\n",ans);
}