题目描述
现在游乐场马上要面临扩建,现在有
m
m
m 个承建商,分别编号为
1
∼
m
1∼m
1∼m ,这些承建商因为都属于一个总公司,所以可以相互协作完成游乐场的扩建任务。但是在同一个子任务内,只能允许一个承建商完成当前的扩建任务,这些承建商完成每个子任务的天数各不相同。游乐场的扩建共有
n
n
n 个任务,现在游乐场想要保证在尽可能短的时间内完成扩建任务。但是对于承建商的选取有严格的需求,比如说,某一个子任务是编号为
i
i
i 的承建商,那么下一个子任务如果更换承建商,则只能更换为编号为
i
+
1
i+1
i+1 的承建商,特殊的,如果当前任务的承建商如果编号为
m
m
m ,那么下一个任务就只能是更换为编号为
1
1
1 的承建商进行。对于更换承建商的次数是没有限制的,对于每一个子任务来说,我们可以更换承建商,也可以不更换。
例如:下面是
3
3
3 个承建商,以及扩建的
4
4
4 个任务每一个承建商完成任务的天数。
承建商1:2,6,1,8
承建商2:3,6,2,6
承建商3:4,2,3,6
例子中,可以选择承建商
1
1
1 来完成整个过程一共花了
2
+
6
+
1
+
8
=
17
2+6+1+8=17
2+6+1+8=17 天,也可以从承建商
2
2
2 开始第一步,然后第二步更换到承建商 33,第三步到承建商
1
1
1,第四步再到承建商
2
2
2,这样一共花了
3
+
2
+
1
+
6
=
12
3+2+1+6=12
3+2+1+6=12 天。你可以发现没有比这样效率更高的选择。你的任务是求出完成扩建任务所花的最少天数。
输入格式
第一行是两个正整数 N N N 和 M M M,表示步数和承建商数。接下来有 M M M 行,每行有 N N N 个非负整数,第 i ( 1 ≤ i ≤ M ) i(1≤i≤M) i(1≤i≤M) 行的第 j j j 个数表示承建商 i i i 完成第 j j j 步所花的天数,天数都不超过 1000000 1000000 1000000。
输出格式
一个正整数,为完成所有步所需最少天数。
样例 #1
样例输入 #1
4 3
2 6 1 8
3 6 2 6
4 2 3 6
样例输出 #1
12
提示
对于 100 100 100% 的数据 1 ≤ N , M ≤ 2000 1≤N,M≤2000 1≤N,M≤2000。
#include <bits/stdc++.h>
using namespace std;
int a[2005][2005];
int dp[2005][2005];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
cin>>a[j][i];
}
}
for(int i=1;i<=m;i++)
{
dp[1][i]=a[1][i];
}
for(int i=2;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(j==1)
{
dp[i][j]=min(dp[i-1][m],dp[i-1][j])+a[i][j];
}
else
{
dp[i][j]=min(dp[i-1][j-1],dp[i-1][j])+a[i][j];
}
}
}
int minx=2e9;
for(int i=1;i<=m;i++)
{
minx=min(minx,dp[n][i]);
}
cout<<minx;
return 0;
}