洛谷P1130红牌(简单DP)
题目描述
某地临时居民想获得长期居住权就必须申请拿到红牌。获得红牌的过程是相当复杂 ,一共包括NNN个步骤。每一步骤都由政府的某个工作人员负责检查你所提交的材料是否符合条件。为了加快进程,每一步政府都派了MMM个工作人员来检查材料。不幸的是,并不是每一个工作人员效率都很高。尽管如此,为了体现“公开政府”的政策,政府部门把每一个工作人员的处理一个申请所花天数都对外界公开。
为了防止所有申请人都到效率高的工作人员去申请。这M×NM \times NM×N个工作人员被分成MMM个小组。每一组在每一步都有一个工作人员。申请人可以选择任意一个小组也可以更换小组。但是更换小组是很严格的,一定要相邻两个步骤之间来更换,而不能在某一步骤已经开始但还没结束的时候提出更换,并且也只能从原来的小组I更换到小组I+1I+1I+1,当然从小组MMM可以更换到小组111。对更换小组的次数没有限制。
例如:下面是333个小组,每个小组444个步骤工作天数:
小组111 : 2,6,1,82, 6 ,1 ,82,6,1,8
小组222 : 3,6,2,63,6, 2, 63,6,2,6
小组333 : 4,2,3,6 4, 2 ,3 ,64,2,3,6
例子中,可以选择小组111来完成整个过程一共花了2+6+1+8=172+6+1+8=172+6+1+8=17天,也可以从小组222开始第一步,然后第二步更换到小组3,第三步到小组111,第四步再到小组222,这样一共花了3+2+1+6=123+2+1+6=123+2+1+6=12天。你可以发现没有比这样效率更高的选择。
你的任务是求出完成申请所花最少天数。
输入格式
第一行是两个正整数NNN和MMM,表示步数和小组数。接下来有MMM行,每行NNN个非负整数,第i+1(1≤i≤M)i+1(1 \le i \le M)i+1(1≤i≤M)行的第j个数表示小组iii完成第j步所花的天数,天数都不超过100000010000001000000。
输出格式
一个正整数,为完成所有步所需最少天数。。
输入输出样例
4 3 2 6 1 8 3 6 2 6 4 2 3 6
12
简单DP,注意一层层更新。
#include <bits/stdc++.h> using namespace std; int a[2005][2005]={0}; int dp[2005][2005]={0};//dp[i][j]表示在第i组完成第j项所花费的最少时间 dp[i][j]=min(dp[i][j-1]+a[i][j],dp[i-1][j-1]+a[i][j])//前提是i-1>0 int n,m; int main() { scanf("%d%d",&n,&m); int i,j; for(i=1;i<=m;i++) { for(j=1;j<=n;j++) { scanf("%d",&a[i][j]); } dp[i][1]=a[i][1]; } int ans=0x3f3f3f3f; for(j=1;j<=n;j++) { for(i=1;i<=m;i++) { if(i==1) { dp[i][j]=min(dp[i][j-1]+a[i][j],dp[m][j-1]+a[i][j]); } else dp[i][j]=min(dp[i][j-1]+a[i][j],dp[i-1][j-1]+a[i][j]); } } for(i=1;i<=m;i++)ans=min(ans,dp[i][n]); cout<<ans; return 0; }