蓝桥杯 算法训练 找金币
题目描述
- 资源限制
时间限制:1.0s 内存限制:256.0MB
- 问题描述
有一个N x N的方格,每一个格子都有一些金币,只要站在格子里就能拿到里面的金币。你站在最左上角的格子里,每次可以从一个格子走到它右边或下边的格子里。请问如何走才能拿到最多的金币。
- 输入格式
第一行输入一个正整数n,以下n行描述该方格。金币数保证是不超过1000的正整数。
- 输出格式
最多能拿金币数量。
- 样例输入
3
1 3 3
2 2 2
3 1 2
- 样例输出
11
- 数据规模和约定
n<=1000
方案1 递归版本 超时 时间复杂度过高 只能过一个数据
#include<iostream>
#include<cmath>
using namespace std;
int n;
int coin[1000][1000];
int f(int i, int j, int coin[1000][1000]){
if(i==1 && j==1){
return coin[0][0];
}
if(i==1 && j>1){
return f(i, j-1, coin) + coin[0][j-1];
}
if(j==1 && i>1){
return f(i-1, j, coin) + coin[i-1][0];
}
return max(f(i-1, j, coin), f(i, j-1, coin)) + coin[i-1][j-1];
}
int main(){
cin>>n;
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
cin >> coin[i][j];
}
}
cout<<f(n, n, coin)<<endl;
return 0;
}
方案2 递归+记忆化搜索 时间复杂度比纯递归版本较低 (过4个数据)
#include<iostream>
#include<cmath>
#include<map>
#include<string>
#include<algorithm>
using namespace std;
int n;
int coin[1000][1000];
map<string, int> mp;
string g(int i, int j){
string ans;
while(j!=0){
ans += char(j%10+'0');
j/=10;
}
ans += '_';
while(i!=0){
ans += char(i%10+'0');
i/=10;
}
reverse(ans.begin(), ans.end());
return ans;
}
int f(int i, int j, int coin[1000][1000]){
if(i==1 && j==1){
return coin[0][0];
}
if(i==1 && j>1){
if(mp.find(g(i, j-1)) == mp.end()){
mp[g(i, j-1)] = f(i, j-1, coin);
}
return mp[g(i, j-1)] + coin[0][j-1];
}
if(j==1 && i>1){
if(mp.find(g(i-1, j)) == mp.end()){
mp[g(i-1, j)] = f(i-1, j, coin);
}
return mp[g(i-1, j)] + coin[i-1][0];
}
if(mp.find(g(i, j-1)) == mp.end()){
mp[g(i, j-1)] = f(i, j-1, coin);
}
if(mp.find(g(i-1, j)) == mp.end()){
mp[g(i-1, j)] = f(i-1, j, coin);
}
return max(mp[g(i-1, j)], mp[g(i, j-1)]) + coin[i-1][j-1];
}
int main(){
cin>>n;
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
cin >> coin[i][j];
}
}
cout<<f(n, n, coin)<<endl;
return 0;
}
方案3 dp动态规划 时间复杂度最低 (n*n), AC
#include<iostream>
#include<cmath>
using namespace std;
int n;
int main(){
cin>>n;
int coin[n][n];
int ans[n][n];
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
cin >> coin[i][j];
}
}
ans[0][0] = coin[0][0];
for(int i=1; i<n; i++){
ans[0][i] = ans[0][i-1] + coin[0][i];
ans[i][0] = ans[i-1][0] + coin[i][0];
}
for(int i=1; i<n; i++){
for(int j=1; j<n; j++){
ans[i][j] = max(ans[i-1][j], ans[i][j-1]) + coin[i][j];
}
}
cout<<ans[n-1][n-1]<<endl;
return 0;
}