其实,这道题并不难,我们这里使用动态规划来解决这道题,这就是传说中的超级玛丽用dp。当然,编者a+b确是也TLE了。在此与各位读者分享一下心得。
本蒟蒻实在是太菜了,导致这道题只想出了一种dp+矩阵的做法,时间复杂度为O(n^2m),不过优化后可变成O(nm)的。
#include<bits/stdc++.h>
using namespace std;
int a[25][65];
int g[23][23];
int f[63][23];
int ans[63][23];
void mul(int x)
{
for(int i=0;i<22;i++)
{
for(int k=0;k<22;k++)
{
ans[x][i]=max(ans[x][i],g[i][k]+f[x][k]);
}
}
}
int main()
{
memset(g,-0x3F,sizeof g);
for(int i=0;i<22;i++)
{
g[i][i]=0;
}
string s[23];
s[1]= "00000000000000003333333300000000000000000000000000000000000000";
s[2]= "00000000000000033333333333300000000000000000000000000000000000";
s[3]= "00000000000000011112222120000000000000000000000000000000000000";
s[4]= "00000000000001221112222211222200000000000000000000000000000000";
s[5]= "00000000000001112222222111111000000000000001110000000000001110";
s[6]= "00000000000000002222222222200000000000000012221000000000012221";
s[7]= "00000000000000011311111110000000000000000012121000000000012121";
s[8]= "00000000000011113333333111111000000000000012121000000000012121";
s[9]= "00000000000222133323333231112222000000000012221000000000012221";
s[10]="00000000000222233333333331122222000000000001110000000000001110";
s[11]="00000000000222233330000333332222000000000000000000000000000000";
s[12]="00000000000001111000000001111000000000000000000000000000000000";
s[13]="00000000000111111000000001111110000000000000000000000000000000";
s[14]="11111111111111111111111111111111111111111111111111111111111111";
s[15]="12221222222121122212222221211222122222212114444444444444444441";
s[16]="11111111111111111111111111111111111111111114444444444444444441";
s[17]="12212222122221122122221222211221222212222111111111111111111111";
s[18]="11111111111111111111111111111111111111111100001444444444410000";
s[19]="12222212222221122222122222211222221222222100001444444444410000";
s[20]="11111111111111111111111111111111111111111100001444444444410000";
s[21]="12122122221221121221222212211212212222122100001444444444410000";
s[22]="11111111111111111111111111111111111111111100001111111111110000";
for(int i=1;i<=22;i++)
{
for(int j=0;j<62;j++)
{
a[i][j]=s[i][j]-'0';
}
}
for(int j=0;j<62;j++)
{
for(int i=1;i<=22;i++)
{
f[j][i-1]=a[i][j];//√
}
}
for(int j=0;j<62;j++)
{
mul(j);
}
for(int j=0;j<62;j++)
{
for(int i=1;i<=22;i++)
{
a[i][j]=ans[j][i-1];
}
}
for(int i=1;i<=22;i++)
{
for(int j=0;j<62;j++)
{
if(a[i][j]==0)
{
cout<<" ";
}
else if(a[i][j]==1)
{
cout<<"#";
}
else if(a[i][j]==2)
{
cout<<".";
}
else if(a[i][j]==3)
{
cout<<"*";
}
else if(a[i][j]==4)
{
cout<<"-";
}
}
cout<<endl;
}
return 0;
}
这是洛谷上AC的代码。
当然,我们可以想办法去处理更复杂一点的超级玛丽游戏的界面,比如1000行,1000列。这时我们可以分析一下g矩阵,发现其除对角线外全是-∞,所以,我们可以用O(n)处理对角线,即可。
O(nm)代码:
#include<bits/stdc++.h>
using namespace std;
int a[25][65];
int g[23][23];
int f[63][23];
int ans[63][23];
void mul(int x)
{
for(int i=0;i<22;i++)
{
// for(int k=0;k<22;k++)
// {
ans[x][i]=max(ans[x][i],g[i][i]+f[x][i]);
// }
}
}
int main()
{
memset(g,-0x3F,sizeof g);
for(int i=0;i<22;i++)
{
g[i][i]=0;
}
string s[23];
s[1]= "00000000000000003333333300000000000000000000000000000000000000";
s[2]= "00000000000000033333333333300000000000000000000000000000000000";
s[3]= "00000000000000011112222120000000000000000000000000000000000000";
s[4]= "00000000000001221112222211222200000000000000000000000000000000";
s[5]= "00000000000001112222222111111000000000000001110000000000001110";
s[6]= "00000000000000002222222222200000000000000012221000000000012221";
s[7]= "00000000000000011311111110000000000000000012121000000000012121";
s[8]= "00000000000011113333333111111000000000000012121000000000012121";
s[9]= "00000000000222133323333231112222000000000012221000000000012221";
s[10]="00000000000222233333333331122222000000000001110000000000001110";
s[11]="00000000000222233330000333332222000000000000000000000000000000";
s[12]="00000000000001111000000001111000000000000000000000000000000000";
s[13]="00000000000111111000000001111110000000000000000000000000000000";
s[14]="11111111111111111111111111111111111111111111111111111111111111";
s[15]="12221222222121122212222221211222122222212114444444444444444441";
s[16]="11111111111111111111111111111111111111111114444444444444444441";
s[17]="12212222122221122122221222211221222212222111111111111111111111";
s[18]="11111111111111111111111111111111111111111100001444444444410000";
s[19]="12222212222221122222122222211222221222222100001444444444410000";
s[20]="11111111111111111111111111111111111111111100001444444444410000";
s[21]="12122122221221121221222212211212212222122100001444444444410000";
s[22]="11111111111111111111111111111111111111111100001111111111110000";
for(int i=1;i<=22;i++)
{
for(int j=0;j<62;j++)
{
a[i][j]=s[i][j]-'0';
}
}
for(int j=0;j<62;j++)
{
for(int i=1;i<=22;i++)
{
f[j][i-1]=a[i][j];//√
}
}
for(int j=0;j<62;j++)
{
mul(j);
}
for(int j=0;j<62;j++)
{
for(int i=1;i<=22;i++)
{
a[i][j]=ans[j][i-1];
}
}
for(int i=1;i<=22;i++)
{
for(int j=0;j<62;j++)
{
if(a[i][j]==0)
{
cout<<" ";
}
else if(a[i][j]==1)
{
cout<<"#";
}
else if(a[i][j]==2)
{
cout<<".";
}
else if(a[i][j]==3)
{
cout<<"*";
}
else if(a[i][j]==4)
{
cout<<"-";
}
}
cout<<endl;
}
return 0;
}
我们可不可以进一步的优化呢?答案是肯定的。我们可以发现,矩阵的对角线上全是0,所以乘完之后相当于一个间接的赋值,而这样看来后面的一整段都是没有意义的所以我们可以直接将打出来的表还原成字符串的即可,时间复杂度O(1),空间复杂度O(n*m).
以下是本蒟蒻的代码:
#include<iostream>
using namespace std;
int main()
{
cout<<" ********"<<endl;
cout<<" ************"<<endl;
cout<<" ####....#."<<endl;
cout<<" #..###.....##...."<<endl;
cout<<" ###.......###### ### ###"<<endl;
cout<<" ........... #...# #...#"<<endl;
cout<<" ##*####### #.#.# #.#.#"<<endl;
cout<<" ####*******###### #.#.# #.#.#"<<endl;
cout<<" ...#***.****.*###.... #...# #...#"<<endl;
cout<<" ....**********##..... ### ###"<<endl;
cout<<" ....**** *****...."<<endl;
cout<<" #### ####"<<endl;
cout<<" ###### ######"<<endl;
cout<<"##############################################################"<<endl;
cout<<"#...#......#.##...#......#.##...#......#.##------------------#"<<endl;
cout<<"###########################################------------------#"<<endl;
cout<<"#..#....#....##..#....#....##..#....#....#####################"<<endl;
cout<<"########################################## #----------#"<<endl;
cout<<"#.....#......##.....#......##.....#......# #----------#"<<endl;
cout<<"########################################## #----------#"<<endl;
cout<<"#.#..#....#..##.#..#....#..##.#..#....#..# #----------#"<<endl;
cout<<"########################################## ############"<<endl;
return 0;
}