算法训练(一)
一、拿金币
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
有一个N x N的方格,每一个格子都有一些金币,只要站在格子里就能拿到里面的金币。你站在最左上角的格子里,每次可以从一个格子走到它右边或下边的格子里。请问如何走才能拿到最多的金币。
输入格式
第一行输入一个正整数n。
以下n行描述该方格。金币数保证是不超过1000的正整数。
以下n行描述该方格。金币数保证是不超过1000的正整数。
输出格式
最多能拿金币数量。
样例输入
3
1 3 3
2 2 2
3 1 2
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。
之後N行,每行為Wi, Vi。
输出格式
一個數,為最大價值。
样例输入
3 20
15 16
6 6
7 5
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; }
未完待续……
不忘初心,方得始终。