有10个气球,每个气球都有一些点写在上面。如果客户射击气球,他将获得等于左气球上的点乘以右气球上的点的点数。客户必须收集最高积分才能赢得此游戏。什么是最大点,他应该以哪种顺序拍摄气球以获得最大分数?
请注意,如果只有一个气球,则返回该气球上的点。
我想检查所有10个!排列以找出最大点。有没有其他方法可以有效地解决这个问题?
答案 0 :(得分:1)
正如我在评论中所说的那样,可以使用带位掩码的动态编程解决方案,我们可以做的是保持位掩码,1
位于bit
的{{1}}意味着已发射i
气球,ith
表示尚未开枪。
因此需要一个只有蒙版的动态编程状态,在每个状态下,我们可以通过迭代所有未被击中的气球并尝试射击它们来找到最大值来转换到下一个状态。
此类解决方案的时间复杂度为:0
,空间复杂度为O((2^n) * n * n)
。
c ++中的代码,未经调试,您可能需要对其进行调试:
O(2^n)
答案 1 :(得分:0)
#include<iostream>
using namespace std;
int findleft(int arr[],int n,int j ,bool isBurst[],bool &found)
{
if(j<=0)
{
found=false;
return 1;
}
for(int i=j-1;i>=0;i--)
{
if(!isBurst[i])
{
return arr[i];
}
}
found = false;
return 1;
}
int findright(int arr[],int n,int j,bool isBurst[],bool &found)
{
if(j>=n)
{
found = false;
return 1;
}
for(int i= j+1;i<=n;i++)
{
if(!isBurst[i])
{
return arr[i];
}
}
found=false;
return 1;
}
int calc(int arr[],int n,int j,bool isBurst[])
{
int points =0;
bool leftfound=true;
bool rightfound=true;
int left= findleft( arr, n-1, j,isBurst , leftfound);
int right = findright( arr,n-1, j,isBurst, rightfound);
if(!leftfound && !rightfound)
{
points+=arr[j];
}
else
{
points+=left*right*arr[j];
}
return points;
}
void maxpoints(int arr[],int n,int cp,int curr_ans,int &ans,int count,bool isBurst[])
{
if(count==n)
{
if(curr_ans>ans)
{
ans=curr_ans;
return;
}
}
for(int i=0;i<n;i++)
{
if(!isBurst[i])
{
isBurst[i]=true;
maxpoints(arr,n,i,curr_ans+calc(arr,n,i,isBurst),ans,count+1,isBurst);
isBurst[i]=false;
}
}
}
int main()
{
int n;
cin>>n;
int ans=0;
int arr[n];
bool isBurst[n];
for(int i=0;i<n;i++)
{
cin>>arr[i];
isBurst[i]=false;
}
maxpoints(arr,n,0,0,ans,0,isBurst);
cout<<ans;
return 0;
}