算法设计与分析第三章习题(1-10)参考代码

**3-1 独立任务最优调度问题

二维数组建立:
dp[i][j] 表示完成i个任务,机器A工作时间为j时,机器B工作的时间。
递推公式如下:
dp[i][j] = min(dp[i-1][j]+b[i],dp[i-1][j-a[i]])
示例:
输入:

6
2 5 7 10 5 2 
3 8 4 11 3 4

输出:
算法设计与分析第三章习题(1-10)参考代码_第1张图片

参考代码:

#include 
#include 
#include 
#include 
#include 
#define inf 0x3f3f3f3f

using namespace std;

//独立任务最优调度问题
int main()
{
    int n;
    cin>>n;
    int a[101];
    int b[101];
    int sum = 0;
    int dp[101][10001];
    for(int i=1; i<=n; i++)
    {
        cin>>a[i];
    }
    for(int i=1; i<=n; i++)
    {
        cin>>b[i];
    }
    memset(dp,0,sizeof(dp));
    // 假设dp[i][j]为完成I个任务时机器工作的时间为J 时B机器工作的时间
    for(int i=1; i<=n; i++)
    {
        sum+=a[i];
        for(int j=0; j<=sum; j++)
          {
              dp[i][j] = dp[i-1][j]+b[i];
              if(j>=a[i])
              {
                  dp[i][j] =  min(dp[i-1][j]+b[i], dp[i-1][j-a[i]]);
              }
          }
    }
    int minn = inf;
    for(int i=0; i<=sum; i++)
    {
       int t = max(i,dp[n][i]);
       minn = min(minn,t);
    }
    cout<<minn<<endl;
    return 0;

}

**3-2 最优批处理问题:
解题思路:
dp[i]表示区间[i,n]上最小总费用
递推公式:
在区间 [i,n] 选一点 j
则dp[i] = min(dp[i],dp[j]+(s+t[i]+t[i+1]+…+t[j-1]) *(f[i]+f[i+1]+…+f[n]))
示例1:
输入:

5 
1
1 3
3 2
4 3
2 3
1 4

输出:

153

参考代码:

#include 
#include 
#include 
#include 
#include 
#define inf 0x3f3f3f3f

using namespace std;
// 3-2 最优批处理问题

int main()
{
    int n,s;
    int t[101],f[101];
    //dp[i] = min(dp[i],dp[j]+(s+t[i]...t[j-1])*(f[i]+..+f[n]))
    int t_sum[101];
    int f_sum[101];
    int dp[101];
    memset(t_sum,0,sizeof(t_sum));
    memset(f_sum,0,sizeof(f_sum));
    memset(dp,inf,sizeof(dp));
    cin>>n>>s;
    for(int i=1; i<=n; i++)
    {
        cin>>t[i]>>f[i];
    }
    
    for(int i=n;i>=1;i--)
    {
        t_sum[i] = t_sum[i+1] + t[i];
        f_sum[i] = f_sum[i+1] + f[i];
    }
    dp[n+1] = 0;
    for(int i=n;i>=1;i--)
    {
        for(int j=i+1; j<=n+1; j++)
        {
            int sum_t = s + t_sum[i] - t_sum[j];
            int sum_f = f_sum[i];
            dp[i] = min(dp[i],dp[j]+sum_t*sum_f);
        }
    }
    cout<<dp[1]<<endl;
    return 0;

}

Sample
Input

4
4 4 5 9

Output

43
54

参考代码:

链接: (注释版代码)

#include 
#include 
#include 
#include 
#include 
#define inf 0x3f3f3f3f

using namespace std;
// 3-3 石子合并问题
int main()
{
    int n;
    int a[202];
    int sum[202];
    int dpmin[202][202];
    int dpmax[202][202];
    cin>>n;
    for(int i=1; i<=n; i++)
    {
        cin>>a[i];
        a[i+n] = a[i];
    }
    memset(sum,0,sizeof(sum));
    memset(dpmin,inf,sizeof(dpmin));
    memset(dpmax,0,sizeof(dpmax));
    for(int i = 1; i<=2*n ;i++)
    {
        sum[i] = sum[i-1] + a[i];
        dpmin[i][i] = 0;
    }
   
    for(int key = 1; key<n; key++)
    {
        for(int i=1; i+key<2*n && i < 2*n; i++)
        {
            int j = i + key;
            for(int k=i; k<j; k++)
            {
                dpmin[i][j] = min(dpmin[i][j],dpmin[i][k]+dpmin[k+1][j]+sum[j]-sum[i-1]);
                dpmax[i][j] = max(dpmax[i][j],dpmax[i][k]+dpmax[k+1][j]+sum[j]-sum[i-1]);
            }
        }
    }
    int minn = inf;
    int maxx = 0;
    for(int i=1; i<=n; i++)
    {
        minn = min(minn,dpmin[i][i+n-1]);
        maxx = max(maxx,dpmax[i][i+n-1]);
    }
    cout<<minn<<endl;
    cout<<maxx<<endl;
    return 0;
}

3-4 数字三角形问题
示例1:

输入:

5
7
3 8
8 1 0
2 7 4 4 
4 5 2 6 5

输出:

30

参考代码:

#include 
#include 
#include 
#include 
#include 
#define inf 0x3f3f3f3f

using namespace std;
// 3-4 数字三角形问题

int main()
{
    int n;
    int dp[101][101];
    memset(dp,0,sizeof(dp));
    cin>>n;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=i; j++)
        {
            cin>>dp[i][j];
        }
    }
    for(int i=n-1; i>=1; i--)
    {
        for(int j=i; j>=1; j--)
        {
            dp[i][j] = dp[i][j] + max(dp[i+1][j],dp[i+1][j+1]);
        }
    }
    cout<<dp[1][1]<<endl;
    return 0;
}

3-5 乘法表问题:
示例1:
输入:

bbbba

输出:
在这里插入图片描述
参考代码:

#include 
#include 
#include 
#include 
#include 
#define inf 0x3f3f3f3f

using namespace std;

// 3-5 乘法表问题

int main()
{
    int dp[101][101][3];
    string s;
    cin>>s;
    int n = s.size();
    memset(dp,0,sizeof(dp));
    for(int i=1; i<=n; i++)
    {
        if(s[i-1] == 'b')  dp[i][i][1] = 1;
        if(s[i-1] == 'a')  dp[i][i][0] = 1;
        if(s[i-1] == 'c')  dp[i][i][2] = 1;
       
    }
    
    //dp[i][j][0] 表示区间(i,j)上表达式的值为0的不同加括号方法数
    for(int op=1; op<n; op++)
    {
        for(int i=1; i+op<=n; i++)
        {
            int j = i + op;
            for(int k=i; k<=j; k++)
            {
                dp[i][j][0] +=  dp[i][k][0]*dp[k+1][j][2] + dp[i][k][1]*dp[k+1][j][2]+ dp[i][k][2]*dp[k+1][j][0];
                dp[i][j][1] +=  dp[i][k][0]*dp[k+1][j][0] + dp[i][k][0]*dp[k+1][j][1]+ dp[i][k][1]*dp[k+1][j][1];
                dp[i][j][2] +=  dp[i][k][1]*dp[k+1][j][0] + dp[i][k][2]*dp[k+1][j][1]+ dp[i][k][2]*dp[k+1][j][2];
    
            }
        }
    }
    cout<<dp[1][n][0]<<endl;
    return 0;

}

3-6 租用游艇问题:
输入:

3
5 15
7

输出:

12

参考代码:

#include 
#include 
#include 
#include 
#include 
#define inf 0x3f3f3f3f

using namespace std;
// 3-6 租用游艇问题
int main()
{
     int n;
     int r[100][101];
     int dp[100][100];
     cin>>n;
     memset(dp,inf,sizeof(dp));
     for(int i=1; i<n; i++)
     {
          for(int j = i+1; j <=n; j++)
          {
               cin>>r[i][j];
               dp[i][j] = r[i][j];
          }
     }
     for(int i=1; i<=n; i++)
     {
          dp[i][i] = 0;
     }
     //dp[100][100];
     for(int op = 1; op<n; op++)
     {
          for(int i=1; i+op<=n; i++)
          {
               int j = i+op;
               for(int k =i; k<j; k++)
               {
                    dp[i][j] = min(dp[i][j],dp[i][k]+dp[k][j]);
               }
          }
     }
     for(int i=1; i<n; i++)
     {
          for(int j=i+1; j<=n; j++)
          {
               cout<<dp[i][j]<<" ";
          }
          cout<<endl;
     }
     cout<<dp[1][n]<<endl;
     return 0;

}

3-7 汽车加油行驶问题
输入:

9 3 2 3 6
0 0 0 0 1 0 0 0 0
0 0 0 1 0 1 1 0 0
1 0 1 0 0 0 0 1 0
0 0 0 0 0 1 0 0 1
1 0 0 1 0 0 1 0 0
0 1 0 0 0 0 0 1 0
0 0 0 0 1 0 0 0 1
1 0 0 1 0 0 0 1 0
0 1 0 0 0 0 0 0 0

输出:

12

参考代码:

#include 
#include 
#include 
#include 
#include 
#define inf 0x3f3f3f3f

using namespace std;
// 3-7 汽车加油行驶问题
int N,K,A,B,C;
int a[100][100];
int dx[4] = {-1,0,1,0};
int dy[4] = {0,-1,0,1};
int dp[100][100]; //(1,1) 到(i,j)的最少费用
int dpk[100][100];  //(1,1) 到(i,j)的步数记录
int nk;
int main()
{
      cin>>N>>K>>A>>B>>C;
      for(int i=1; i<=N ;i++)
      {
           for(int j=1; j<=N; j++)
           {
                cin>>a[i][j];
           }
      }
      for(int i=1; i<=N; i++)
      {
           for(int j=1; j<=N; j++)
           {
                dp[i][j] = inf;
                dpk[i][j] = K;
           }

      }
      dp[1][1] = 0; dpk[1][1] = K;
      for(int i=1; i<=N; i++)
      {
           for(int j=1; j<=N; j++)
           {
                if(i == 1 && j == 1)
                {
                     continue;
                }
                int minmoney = inf ,minstep;
                int tepmoney ;
                int tepstep;
                for(int k = 0; k < 4; k++)
                {
                   int ti = i + dx[k];
                   int tj = j + dy[k];
                   if(ti<1 || ti>N || tj<1 || tj >N)
                   {
                        continue;
                   }
                   tepmoney = dp[ti][tj];
                   tepstep = dpk[ti][tj] - 1;
                   //条件2
                   if(ti>i || tj>j)
                   {
                        tepmoney += B;
                   }
                   // 条件3
                   if(a[i][j])
                   {
                        tepmoney += A;
                        tepstep = K;
                   }
                   //条件4
                   if(a[i][j] == 0 && tepstep == 0 && (i != N || j != N))
                   {
                        tepmoney += A+C;
                        tepstep = K;

                   }
                   //
                   if(minmoney > tepmoney)
                   {
                        minmoney = tepmoney;
                        minstep = tepstep;
                   }

                }
                if(dp[i][j] > minmoney)
                {
                     dp[i][j] = minmoney;
                     dpk[i][j] = minstep;
                }
           }
      }
    cout<<endl;
    for(int i=1; i<=N; i++)
    {
         for(int j=1; j<=N; j++)
         {
              cout<<dp[i][j]<<" ";
         }
         cout<<endl;
    }
    cout<<dp[N][N]<<endl;
    return 0;
}

3-8 最小m段和问题
输入:

7 3
34 67 23 45 56 14 24

输出:

101

参考代码:

#include 
#include 
#include 
#include 
#include 
#define inf 0x3f3f3f3f

using namespace std;
// 3-8 最小m段和问题
int main()
{
     int n,m;
     int a[100];
     int sum[100];
     int dp[100][100];
     cin>>n>>m;
     for(int i=1; i<=n; i++)
     {
          cin>>a[i];
         dp[i][1] = dp[i-1][1] + a[i];
     }

     //dp[i][j] 表示区间(1,i)分为j段时的最小和问题
     for(int i=2; i<=n; i++)
     {
          for(int j=2; j<=m&&j<=i; j++)
          {
               dp[i][j] = inf;
               for(int k=2; k<i; k++)
               {
                  int temp = max(dp[k][j-1],dp[i][1] - dp[k][1]);
                  dp[i][j] = min(dp[i][j],temp);
               }
              
          }
     }
     cout<<dp[n][m]<<endl;
     return 0;
}

3-9 圈乘运算问题
3-10 最大长方体问题
输入:

3 3 3
0 -1 2
1 2 2
1 1 -2
-2 -1 -1
-3 3 -2
-2 -3 1
-2 3 3
0 1 3
2 1 -3

输出:

14

参考代码:

#include 
#include 
#include 
#include 
#include 
#define inf 0x3f3f3f3f

using namespace std;
// 3-10 最大长方体问题
int m,n,p;
int mp[51][51][51];
int maxsum_1D(int c[])
{
    int flag = 0,sum = 0;
    for(int i=1; i<=p; i++)
    {

        if(flag>0)
        {
            flag += c[i];
        }
        else
        {
            flag = c[i];
        }
        if(flag > sum)
        {
            sum = flag;
        }
    }
    return sum;
}
int maxsum_2D(int b[][51])
{

    int c[51];
    int maxsum,sum=0;
    for(int i=1; i<=n; i++)
    {

        for(int tp =1; tp<=p; tp++)
        {

            c[tp] = 0;
        }
        for(int j=i; j<=n; j++)
        {

            for(int tp = 1; tp<=p; tp++)
            {

               c[tp] += b[j][tp];
            }
            maxsum = maxsum_1D(c);
            if(maxsum > sum)
            {

                sum = maxsum;
            }
        }
    }
    return sum;
}
int maxsum_3D()
{
    int b[51][51];
    int maxsum,sum=0;
    for(int i=1; i<=m; i++)
    {
        for(int tn = 1; tn<=n; tn++)
        {

            for(int tp=1; tp<=p; tp++)
            {

                b[tn][tp] = 0;
            }
        }
        for(int j=i; j<=m; j++)
        {

            for(int tn=1; tn<=n; tn++)
            {

                for(int tp=1; tp<=p; tp++)
                {
                    b[tn][tp] += mp[j][tn][tp];
                }
            }
            maxsum = maxsum_2D(b);
            if(sum < maxsum)
            {
                sum = maxsum;
            }

        }
    }
    return sum;
}
int main()
{
   cin>>m>>n>>p;
   for(int i=1; i<=m; i++)
   {
       for(int j=1; j<=n; j++)
       {
           for(int k=1; k<=p;k++)
           {
               cin>>mp[i][j][k];
           }
       }
   }
   cout<<maxsum_3D()<<endl;
   return 0;
}

你可能感兴趣的:(动态规划,算法,动态规划,c++)