poj 1050 求和问题

本文介绍了一种使用动态规划解决二维矩阵中求最大子矩阵元素和的问题,通过将子矩阵转换为一维问题来简化计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:给定一个n*n的矩阵,求一个子矩阵,使得该矩阵的元素之和最大。

思路:经典的DP。由一维到二维。

      1.必须先了解一维的情况,对于一维的数组而言,则转化为用DP求最大连续子序列,DP的状态方程为:sum[i] = max(sum[i-1] + num[i], 0)。

      例如: num[]: -5, 7, -2, -6, 5, -1, 4

             sum[]:  0, 7, 5, 0, 5,  4,  8

      2.对于二维的情况,则可转化为一维。将子矩阵的所有相同列的元素加在一起,问题就解决了。

      例如: 若子矩阵为: -1, -2, -3,  5,  4

                          2, -5,  4,  7,  6

                          5,  5, -6, -2, -7

              则now[]为: 6,  3, -5, 10, -3

代码:

#include<iostream>
using namespace std;
const int Max = 105;

int max(int a, int b)
{
    return a > b ? a : b;
}

int main()
{
    int n, i, j, k, row, col, sum, ans;
    int num[Max][Max], now[Max];
    cin >> n;
    row = col = n;
    for(i = 0; i < row; i ++)
        for(j = 0; j < col; j ++)
            cin >> num[i][j];
		ans = sum = 0;
		for(i = 0; i < row; i ++)
		{
			memset(now, 0, sizeof(now));
			for(j = i; j < row; j ++)    //  求第i行到第j行的子矩阵。
				for(k = 0, sum = 0; k < col; k ++)
				{ 
					now[k] += num[j][k];
					sum = max(sum + now[k], 0);
					if(sum > ans) 
						ans = sum;
	
				}
		}
		cout << ans << endl;
		return 0;
}

 

 

 

#include <stdio.h> #include <stdlib.h> typedef int status; #define OK 1 #define ERROR 0 #define OVER_FLOW -2 #define TRUE 1 #define FALSE 0 #define LIST_INIT_SIZE 2 #define LIST_INCREASEMENT 2 #define N 6 typedef struct { int value; int quantity; int functionCount; } marbleType; typedef struct { marbleType *marble; int length; int listSize; } sqListMarble; typedef struct { status *state; int length; int listSize; } resultList; FILE *fp;// status initList_sq(sqListMarble *list); status initResultList(resultList *list); status sqListInsertM(sqListMarble *list,int quantity,int value); status insertResultList(resultList *list,status state); status calculate(int totalValue,sqListMarble *marbleList); int getCurMarbleValue(sqListMarble *marbleList,int marbleNumber); void printResult(resultList *list); main() { resultList result; int i,quantity,totalValue; sqListMarble marbleList; fp = fopen("data.txt","r");// initResultList(&result); while(1) { initList_sq(&marbleList); totalValue = 0; for(i = 0;i < N;i++) { fscanf(fp," %d",&quantity);// //scanf(" %d",&quantity); if(quantity) { sqListInsertM(&marbleList,quantity,i + 1); totalValue += quantity * (i + 1); } } if(!totalValue) break; insertResultList(&result,calculate(totalValue, &marbleList)); } printResult(&result); fclose(fp); } status initList_sq(sqListMarble *list) { list->marble = (marbleType *)calloc(LIST_INIT_SIZE,sizeof(marbleType)); if(!list->marble) exit(OVER_FLOW); list->length = 0; list->listSize = LIST_INIT_SIZE; return OK; } status sqListInsertM(sqListMarble *list,int quantity,int value) { marbleType *newBase; if(list->length >= list->listSize) { newBase = (marbleType *)realloc(list->marble,(list->listSize + LIST_INCREASEMENT) * sizeof(marbleType)); if(!newBase) exit(OVER_FLOW); list->marble = newBase; list->listSize += LIST_INCREASEMENT; } (list->marble + list->length)->quantity = quantity; (list->marble + list->length)->value = value; (list->marble + list->length)->functionCount = 0; list->length++; return OK; } status calculate(int totalValue,sqListMarble *marbleList) { int halfValue ,i,marbleNumber; int functionAmount = 1,value = 0; if(totalValue % 2) return FALSE; halfValue = totalValue / 2; for(i = 0; i < marbleList->length;i++) functionAmount *= (marbleList->marble + i)->quantity + 1; marbleList->marble->functionCount = -1; for(i = 0;i < functionAmount;i++) { value = 0; for(marbleNumber = 0;marbleNumber < marbleList->length;marbleNumber++) value += getCurMarbleValue(marbleList,marbleNumber); //putchar('\n');// if(value == halfValue) return TRUE; } return FALSE; } int getCurMarbleValue(sqListMarble *marbleList,int marbleNumber) { marbleType *marble = marbleList->marble + marbleNumber; if(marble == marbleList->marble) marble->functionCount++; if(marble->functionCount == marble->quantity + 1) { if(marbleList->marble + marbleList->length - 1 != marble ) (marble + 1)->functionCount++; marble->functionCount = 0; } //printf(" %d ",curCount);// return marble->functionCount * marble->value; } void printResult(resultList *list) { int i; for(i = 0;i < list->length;i++) { printf("Collection #%d:\n",i + 1); if(*(list->state + i) == 1) { printf("Can be divided.\n"); } else { printf("Can't be divided.\n"); } printf("\n"); } return; } status initResultList(resultList *list) { list->length = 0; list->listSize = LIST_INIT_SIZE; list->state = (status *)calloc(LIST_INIT_SIZE,sizeof(status)); if(!list->state) exit(OVER_FLOW); return OK; } status insertResultList(resultList *list,status state) { if(list->length >= list->listSize) { list->state = (status *)realloc(list->state,(list->listSize + LIST_INCREASEMENT) * sizeof(status)); if(!list->state) exit(OVER_FLOW); list->listSize += LIST_INCREASEMENT; } *(list->state + list->length) = state; list->length++; return OK; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值