计拔(1)3. 大富翁的新规(深度优先搜索)

【问题描述】

现有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;
}

写题还是得细心一点!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Awars_zpp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值