【问题描述】
现有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
【评分标准】
因为此题要考虑到走格子的各种不同路径,故用DFS算法解决(水平有限,只能这样了QAQ):
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[101],book[101],n,temp,cnt=-1;//开全局变量,便于函数访问
class square{
public:
square()
{
turn=0;//初始化操作
}
ll num;//格子上所标的数字
ll turn;//没遍历过的都为0,遍历过的都为1,每次循环结束后清零
};
void dfs(ll step,square *arr)
{
if(step==n+1)//每轮深搜结束
{
temp=0;//每轮结束后temp恢复初始化,防止对下一轮遍历造成影响
for(ll i=1;i<=n;i++)
{
ll p,q;//左右两个数字,作用相当于指针,分别向左向右查找到第一个符合要求的方格
p=a[i]+1;q=a[i]-1;
while(arr[p].turn!=0)
{
p++;
}
while(arr[q].turn!=0)
{
q--;
}
temp+=(arr[a[i]].num*arr[p].num*arr[q].num);
arr[a[i]].turn=1;//表示已经访问过该格子,后续不再访问
}
if(cnt<temp)
{
cnt=temp;//若一个轮回结束后遇到比自己大的cnt,则替换
}
for(ll j=0;j<n+2;j++)
{
arr[j].turn=0;//这里本来想用fill的,结果忘了咋搞,于是省事直接for了
}
return;
}
for(ll i=1;i<=n;i++)
{
if(book[i]==0)
{
a[step]=i;
book[i]=1;//表示在深搜过程中已经遍历过
dfs(step+1,arr);//继续深搜
book[i]=0;//恢复初始状态
}
}
return;
}
int main()
{
ll N;
cin>>N;
square arr[N+2];//此处N+2是为了防止数组越界,干脆我给他一个头一个尾,访问到头尾时一定停下
arr[0].num=1;arr[N+1].num=1;//按照题目要求,越界部分数字全为1
for(ll i=1;i<=N;i++)
{
cin>>arr[i].num;
}
n=N;
dfs(1,arr);
cout<<cnt<<endl;
system("pause");
return 0;
}
PS:这种题不比期末那种磨人耗时间的大模拟强多了?