2014年上海邀请赛C Seam Carving(二维dp)

来源:互联网 发布:数论相似度算法 编辑:程序博客网 时间:2024/05/16 11:25

题目地址

题目大意:给出n,m,以及一个n*m的矩阵,求在每一行选一个值使得和最小,且选值时满足相邻2行的列数之差绝对值<=1,输出从第一行到最后一行每一行所选择的是第几列

解题思路:二维dp,因为题意要求正序输出,所以倒序求和。dp[i][j]表示第i行选第j个数的最小和,aft[i][j]表示第i行选第j个数时第i+1行所选的列(一直保证和最小)

#include <iostream>#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>#include <queue>#include <string>#include <map>#include <stack>#include <list>using namespace std;const int maxn = 100+10;int num[maxn][maxn];int dp[maxn][maxn],aft[maxn][maxn];//dp[i][j]记录从最后一行到第i行且第i行选第j个数时的最小和//aft[i][j]记录第i行选第j个数时第i+1行的选择int main(){    int t,n,m;    int cas = 1;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);        memset(num,0,sizeof(num));        memset(dp,0,sizeof(dp));        memset(aft,-1,sizeof(aft));        for(int i = 1; i <= n; i++)        {            num[i][0] = 1<<30;num[i][m+1] = 1<<30;//初始化边界            dp[i][0] = 1<<30;dp[i][m+1] = 1<<30;            for(int j = 1; j <= m; j++)            {                scanf("%d",&num[i][j]);            }        }        for(int i = 0; i <= m; i++) //因为要正序输出,所以从最后一行开始倒着往前推            dp[n][i] = num[n][i];        for(int i = n-1; i >= 1; i--)        {            for(int j = 1; j <= m; j++)            {                dp[i][j] = dp[i+1][j+1]; //假设i+1行所选的值                aft[i][j] = j+1;                if(dp[i+1][j] < dp[i][j])                {                     dp[i][j] = dp[i+1][j];                     aft[i][j] = j;                }                if(dp[i+1][j-1] < dp[i][j])                {                    dp[i][j] = dp[i+1][j-1];                    aft[i][j] = j-1;                } //确定第i+1行的取值                dp[i][j] += num[i][j];            }        }        printf("Case %d\n",cas++);        int tmp = dp[1][m];        int flag = m;        for(int i = m-1; i >= 1; i--) //确定第一行的取值并满足题目的输出最右        {            if(dp[1][i] < tmp)            {                tmp = dp[1][i];                flag = i;            }        }        printf("%d",flag);        for(int i = 1; i < n; i++) //根据上一行确定下一行的取值        {            printf(" %d",aft[i][flag]);            flag = aft[i][flag];        }        printf("\n");    }    return 0;}


0 0
原创粉丝点击