动态规划

1、矩阵连乘积问题
void MatrixChain (int n)
{
    for(int i=1; i<=n; i++)
        m[i][i]=0;
    for(int r=2; r<=n; r++)
    {
        for(int i=1; i<=n-r+1; i++)
        {
            int j=i+r-1;
            m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j];
            s[i][j]=i;
            for(int k=i+1; k<j; k++)
            {
                int t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
                if(t<m[i][j])
                {
                    m[i][j]=t;
                    s[i][j]=k;
                }

            }
        }
    }
}

//计算矩阵连乘积最优解的递归算法
void TraceBack(int i, int j)
{
    if(i==j) cout<<i;
    else
    {
        cout<<"(";
        TraceBack(i,s[i][j]);
        TraceBack(s[i][j]+1,j);
        cout<<")";
    }
}

//计算矩阵连乘积的备忘录算法
int LookupChain  (int i, int j)
{
    if(m[i][j]>0)  return m[i][j];
    if(i==j) return 0;
    int u=LookupChain(i,i)+LookupChain(i+1,j)+p[i-1]*p[i]*p[j];
    s[i][j]=i;
    for(int k=i+1; k<j; k++)
    {
        int t = LookupChain(i,k)+LookupChain(k+1,j)+p[i-1]*p[k]*p[j];
        if(t<u)
        {
            u=t;
            s[i][j]=k;
        }
    }
    m[i][j]=u;
    return u;
}

2、最长公共子序列
void LCSLength (int m, int n, const char x[],char y[])
{
    int i,j;
    for(i=1; i<=m; i++) c[i][0]=0;
    for(j=1; j<=n; j++) c[0][j]=0;
    for (i = 1; i <= m; i++)
          for (j = 1; j <= n; j++)
        {
            if(x[i]==y[j])
            {
                c[i][j]=c[i-1][j-1]+1;
                b[i][j]=1;
            }
            else if(c[i-1][j]>=c[i][j-1])
            {
                c[i][j]=c[i-1][j];
                b[i][j]=2;
                else
                {
                    c[i][j]=c[i][j-1];
                    b[i][j]=3;
                }
            }
        }
}
//构造最长公共子序列
void LCS(int i,int j,char x[])
{
    if(i==0||j==0) return ;
    if(b[i][j]==1)
    {
        LCS(i-1,j-1,x);
        cout<<x[i];
    }
    else if(b[i][j]==2)
        LCS(i-1,j,x);
    else
        LCS(i,j-1,x);
}

3、最大子段和
//最优解
int MaxSum(int n,int &besti, int &bestj)
{
    int sum=0;
    int b=0;
    int begin=0;
    for(int i=0; i<n; i++)
    {
        if(b>0)
            b+=a[i];
        else
        {
            b=a[i];
            begin=i;
        }
        if(b>sum)
        {
            sum=b;
            besti = begin;
            bestj = i;
        }
    }
    return sum;
}

4、0-1背包问题(逆推)
void knapsack(int c, int n)
{
    int jMax=min {w[n]-1,c}
             for( int j=0; j<=jMax; j++)   p[n][j]=0;
    for( int j=w[n]; j<=c; j++)    p[n][j]=v[n];
    for( int i=n-1; i>1; i--)
    {
        jMax=min(w[i]-1,c);
        for( int j=0; j<=jMax; j++)
            p[i][j]=p[i+1][j];
        for(int j=w[i]; j<=c; j++)
            p[i][j]=max(p[i+1][j], p[i+1][j-w[i]]+v[i]);
    }
    p[1][c]=p[2][c];
    if (c>=w[1])   p[1][c]=max(p[1][c], p[2][c-w[1]]+v[1]);
}
//最优解
void traceback( int c, int n, int x[ ])
{
    for(int i=1; i<=n; i++)
    {
        if(p[i][c]==p[i+1][c])
            x[i]=0;
        else
        {
            x[i]=1;
            c[i]-=w[i];
        }
        x[n]=(p[n][c])? 1:0;
    }
}

5、最长单调递增子序列
int LIS_n2(int n)
{
    int b[NUM]= {0}; //辅助数组
    int i,j;
    int max=0;
    b[1]=1;
    for (i=2; i<=n; i++)
    {
        int k=0;
        for (j=1; j<i; j++)  //0~i-1之间,b的最大值
            if (a[j]<=a[i] && k<b[j])
                k=b[j];
          b[i] = k+1;
          if (max<b[i]) max=b[i];
    }
    return max;
}

6、数字三角形问题
int triangle(int n)
{
     int i, j;
     for (i=n-2; i>=0; i--)
         for (j=0; j<=i; j++)
              if( tri[i+1][j] >tri[i+1][j+1])
                   tri[i][j] += tri[i+1][j];
              else tri[i][j] += tri[i+1][j+1];
     return  tri[0][0];
}

7、FatMouse's Speed
//下面是针对排序后的数组
int count[1001] = {0};		//序列的最大长度
int path[1001] = {0}; 		//序列的前驱
count[1] = 1;
for(int i = 2; i < n; i++)
{
 for(int j = 1; j<i; j++)
  if(mice[i].weight>mice[j].weight  && mice[i].speed<mice[j].speed)
   if(count[i] < count[j])		//得到了更长的序列
   {
    count[i] = count[j];
    path[i] = j;			//记录前驱
   }
 count[i]++;
}
//查找最大的序列长度
int max = 0;		//最大长度
int pos;		//最大长度元素所在位置
for(int i = 1; i < n; i++)
 if(count[i] > max)
 {
  max = count[i];
  pos = i;
 }
//输出最大长度
cout<<max;

//输出子序列序号的算法
void output(int path[], int pos)
{
 if(pos == 0) return;
 output(path, path[pos]);
 cout<<mice[pos].id;
}

8、平分大理石块
void DP(int sum)
{
 int i,j,k;
 int mid = sum/2;
 //大理石的状态数组
 char visit[200];
 memset(visit, 0, sizeof(visit));
 int t;
 visit[0] = 1;
 //对每种价值的大理石块
 for(i=1; i<=6; i++)
  for(j=mid; j>=0; j- -)
   //价值为j的分配方案存在
   if (visit[j])
    for(k=1; k<=a[i]; k++)
    {
     t = j+i*k;
     if (t>mid) break;
      //增加k块价值为i大理石,该平分方案仍然是成立的
     else visit[t] = 1;
     if (t==mid) {	//找到了分配方案
      printf("Can be divided.\n\n");
      return;
     }
    }
 cout<<"Can't be divided.";
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值