【问题描述】
现有n块地板格子,序号从0到n-1,每块格子上有一个数字,以数组sum[n]的方式表示。现在要求你将这n块地板格子都踩过一遍,踩到序号为i的格子则可以获得sum[i-1]*sum[i]*sum[i+1]万元的资产,若i-1或者i+1超过了数组边界,则此时sum[i-1]*sum[i]*sum[i+1]式子中超出边界的元素数值记为1。按照什么样的顺序去踩地板才能获得最大资产呢?
【输入形式】
第一行输入n代表地板格子的个数,第二行输入n个数值,每个数值对应这n个格子上所标的数字
【输出形式】
输出一个数代表能获取的最大资产金额
【样例输入】
4
3 1 5 8
【样例输出】
167
【样例说明】
sum = [3,1,5,8]-->[3,5,8]-->[3,8]-->[8]-->[]
money = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167
分析:
我首先的想法是贪心,但其实应该很快就排除贪心,因为前一步的选择会对下一步造成影响;之后我想是不是得dp,但是不会。之后想,可能得完全遍历,如果不追求速度的话,这样肯定是能过的。把每一种踩格子的路径都模拟一遍,选出最大的money。为了实现起来好写,我选择深度优先搜索。
代码如下(花了一天的时间找一个小错误,让我一度以为不该搜索):
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll ans=-9999999;
ll n;
struct node{
ll m;
bool vis;
}sum[9999999];
void dfs(ll s,ll cnt,ll step)
{
if(step==n){
ans=max(ans,cnt);
return;
}
for(ll i=1;i<=n;i++){
if(!sum[i].vis){
sum[i].vis=true;
ll temp=sum[i].m;
for(ll k=i-1;k>=0;k--){
//原:for(ll k=s-1;k>=0;k--)
if(!sum[k].vis) {
temp*=sum[k].m;
break;
}
}
for(ll j=i+1;j<=n+1;j++){
//原:for(ll j=s+1;j<=n+1;j++)
if(!sum[j].vis){
temp*=sum[j].m;
break;
}
}
cnt+=temp;
dfs(i,cnt,step+1);
sum[i].vis=false;
cnt-=temp;
}
}
}
int main()
{
cin>>n;
sum[0].m=1;
sum[n+1].m=1;
for(ll i=1;i<=n;i++) cin>>sum[i].m;
for(ll i=1;i<=n;i++){
sum[i].vis=true;
ll cnt=sum[i].m*sum[i+1].m*sum[i-1].m;
dfs(i,cnt,1);
sum[i].vis=false;
}
cout<<ans<<endl;
return 0;
}
写题还是得细心一点!!!