算法训练(一)

一、拿金币

资源限制

时间限制:1.0s   内存限制:256.0MB

问题描述

  有一个N x N的方格,每一个格子都有一些金币,只要站在格子里就能拿到里面的金币。你站在最左上角的格子里,每次可以从一个格子走到它右边或下边的格子里。请问如何走才能拿到最多的金币。

输入格式

  第一行输入一个正整数n。
  以下n行描述该方格。金币数保证是不超过1000的正整数。

输出格式

  最多能拿金币数量。

样例输入

3
1 3 3
2 2 2
3 1 2

样例输出

11

数据规模和约定

  n<=1000

问题分析(DP)

  由于只能向右或者向下走,所以走到第 i 行第 j 列的最大值,即为走到第 i-1 行第 j 列的值与走到第i行第 j-1 列的最大值与第 i 行第 j 列的值之和,最终数组右下角的值即为最大值。

c++实现

#include<iostream>
#include<iomanip>
#include<algorithm>

using namespace std;

int m[1001][1001]={0};

int main()
{
    int n;

    cin>>n;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            cin>>m[i][j];
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            m[i][j]=max(m[i][j]+m[i][j-1],m[i][j]+m[i-1][j]);
        }
    }
    cout<<m[n][n]<<endl;

    return 0;
}

二、完全背包问题

资源限制

时间限制:1.0s   内存限制:256.0MB

问题描述

  有一個背包,容量為M。有N種物品,每種物品有其體積Wi與價值Vi。將這些物品的一部分放入背包,每種物品可以放任意多個,要求總體積不超過容量,且總價值最大。

输入格式

  第一行為N, M。
  之後N行,每行為Wi, Vi。

输出格式

  一個數,為最大價值。

样例输入

3 20
15 16
6 6
7 5

样例输出

18

数据规模和约定

  N, M<=1000。

问题分析(DP)

  0-1背包问题:

   同理,只不过该题中的同一物品可装多个,即:wv[i][j]=max(wv[i-1][j],vi[i]+wv[i][j-wi[i]])

c++实现

#include<iostream>
#include<iomanip>
#include<algorithm>

using namespace std;

int wi[1001]={0},vi[1001]={0},wv[1001][1001]={0};    //wv表示可拿的最大价值

int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>wi[i]>>vi[i];
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(j>=wi[i])
            {
                wv[i][j]=max(wv[i-1][j],vi[i]+wv[i][j-wi[i]]);
            }
        }
    }
    cout<<wv[n][m]<<endl;
    return 0;
}

未完待续……

 

posted @ 2022-03-03 22:01  z9m8r8  阅读(55)  评论(0编辑  收藏  举报