【问题标题】:Shoot balloons and Collect Maximum Points拍摄气球并收集最高分
【发布时间】:2016-04-27 09:40:29
【问题描述】:

有 10 个气球,每个气球上都写有一些点。如果客户射气球,他将获得等于左侧气球上的点数乘以右侧气球上的点数的积分。客户必须收集最高分才能赢得这场比赛。什么是最高分?他应该按什么顺序发射气球以获得最高分?

请注意,如果只有一个气球,则返回该气球上的点。

我正在尝试检查所有 10 个!排列以找出最大点。有没有其他方法可以有效地解决这个问题?

【问题讨论】:

  • 如果他射最左边或最右边的气球怎么办? 0分?
  • 如果他在最左边或最右边发射任何气球,那么左边或右边将乘以1分
  • 我认为可以使用带位掩码的动态编程来解决。
  • 直觉上,总是在得分最多的那个旁边(左或右)射击气球似乎是件好事。不确定这是否总是会导致最佳解决方案。
  • 在某些情况下会失败

标签: algorithm recursion dynamic-programming


【解决方案1】:

正如我在 cmets 中所说,使用位掩码的动态编程解决方案是可能的,我们可以做的是保留一个位掩码,其中 bit 处的 1 索引为 i 意味着 ith 气球已经拍摄,0 表示它没有被拍摄。

因此需要一个只有掩码的动态编程状态,在每个状态下,我们可以通过遍历所有尚未发射的气球并尝试发射它们以找到最大值来转换到下一个状态。

这种解决方案的时间复杂度为:O((2^n) * n * n),空间复杂度为O(2^n)。

c++中的代码,它没有被调试,你可能需要调试它:

int n = 10, val[10], dp[1024];    //set all the values of dp table to -1 initially

int solve(int mask){
    if(__builtin_popcount(mask) == n){
        return 0;
    }
    if(dp[mask] != -1) return dp[mask];

    int prev = 1, ans = 0;
    for(int i = 0;i < n;i++){
        if(((mask >> i) & 1) == 0){ //bit is not set
            //try to shoot current baloon
            int newMask = mask | (1 << i);
            int fwd = 1;
            for(int j = i+1;j < n;j++){
                if(((mask >> j) & 1) == 0){
                    fwd = val[j];
                    break;
                }
            }
            ans = max(ans, solve(newMask) + (prev * fwd));
            prev = val[i];
        }
    }
    return dp[mask] = ans;
}

【讨论】:

【解决方案2】:

#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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多