去年的算法作业题_01背包_矩阵相乘

   偶然发现了去年上算法分析课程时作业题目的解答程序,发给有需要的朋友参考。

(一)动态规划法解01背包问题

01背包问题例如:某商店有n个物品,第i个物品的价值为v,重量为w。背包的容量为W。那么如何选取物品,使得背包里的物品的价值总和最大?

#include "stdafx.h"
#include <stdlib.h>
#include "iostream.h"
#include <time.h>

const int RandValue=200;
const int RandValue2=50;
int Max=0;

const int N=700;
const int W=2000;
int w[N];
int v[N];
/*
const int N=5;
const int W=17;
int w[N]={3,4,7,8,9};
int v[N]={4,5,10,11,13};
*/
int c[N+1][W+1];          //记录表
int x[N+1];

void getValue(void)
{
  w[0]=1+rand()%RandValue;
  v[0]=1+rand()%RandValue;
  for(int i=1;i<N;i++)
  {
   w[i]=w[i-1]+rand()%RandValue2;
   v[i]=w[i]+rand()%RandValue2;
  }
}

void OutPut(int M[N])
{
  for(int i=0;i<N;i++)
  {
  cout<<M[i]<<endl;
  }
}

void OutPutC(void)
{  
    cout<<"c[1][1] → c["<<N<<"]["<<W<<"]"<<endl;
 for(int i=1;i<N+1;i++)
 {   cout<<i<<"│"<<" ";
  for(int j=1;j<W+1;j++)
  {int t1=c[i][j]/10;
   int t2=c[i][j]/100;
   if(t1==0 && t2==0){cout<<c[i][j]<<"   ";}
   if(t1!=0 && t2==0){cout<<c[i][j]<<"  ";}
   if(t1!=0 && t2!=0){cout<<c[i][j]<<" ";}
  }
  cout<<endl;
 }
}

///Begin_RECUR
int RECUR_KNAP(int i,int temp_W)  //开始i=0   (i为第i+1个物品)

    int max=0;

 for(i;i<N;i++)
 { 
  if(temp_W-w[i]>=0)
  { int value=RECUR_KNAP(i+1,temp_W-w[i]);
   if(value+v[i]>max)
   {
   max=value+v[i];
   }
  }
 }
  return max;
}
/End_RECUR

/Begin_KNAPSACK
void KNAPSACK_DP(int n,int temp_W)
{
 for(int temp_w=0;temp_w<=temp_W;temp_w++)
 {
  c[0][temp_w]=0;
 }
 for(int i=1;i<=n;i++)
 {
  c[i][0]=0;
  for(temp_w=1;temp_w<=temp_W;temp_w++)
  {
   if(w[i-1]<=temp_w)
   {
    if(v[i-1]+c[i-1][temp_w-w[i-1]]>c[i-1][temp_w])
    {
    c[i][temp_w]=v[i-1]+c[i-1][temp_w-w[i-1]];
    }else
    {
    c[i][temp_w]=c[i-1][temp_w];
    }
   }else
   {
   c[i][temp_w]=c[i-1][temp_w];
   }
  }
 }
}

void OUTPUT_SACK(int temp_w)
{   x[0]=0;
 for(int i=N;i>=1;i--)
 {
  if(c[i][temp_w]==c[i-1][temp_w])
  {
   x[i]=0;
  }
  else
  {
  x[i]=1;
  temp_w=temp_w-w[i-1];
  }
 }
}
///End_KNAPSACK

void OutPutX(void)
{
    for(int i=1;i<=N;i++)
 {
 cout<<"x["<<i<<"]="<<x[i]<<endl;
 }
}

/

int main(int argc, char* argv[])
{
    clock_t start1, finish1,start2, finish2;

 getValue();      //获取随机值
 cout<<"分别用递归和动态规划算法解01背包问题/n"<<"物品个数:"<<N<<"/n"<<"背包容量:"<<W<<endl;
 cout<<"/n解:/n是否打印物品重量和价值数组(Y/N)?"<<endl;
 char A,B;
 cin>>A;
 if(A=='Y' || A=='y')
 {
 OutPut(w);       //显示重量数组
 OutPut(v);       //显示价值数组
 }
 cout<<"运行....."<<"/n"<<endl;

 start1 = clock();
 Max=RECUR_KNAP(0,W);   //递归算法
 finish1=clock();

    start2 = clock();
 KNAPSACK_DP(N,W);    //动态规划算法
 OUTPUT_SACK(W);      //计算解向量
 finish2 = clock();

 cout<<"递归算法:"<<endl;
 cout<<"最优解:"<<Max<<endl;
 cout<<"用时(ms):"<<finish1-start1<<endl;
 cout<<endl;
 cout<<"动态规划算法:"<<endl;
 cout<<"最优解:"<<c[N][W]<<endl;
 cout<<"用时(ms):"<<finish2-start2<<endl;
 cout<<"是否打印辅助表(Y/N)?"<<endl;
 cin>>A;
 cout<<"是否打印解向量(Y/N)?"<<endl;
 cin>>B;
 if(A=='Y' || A=='y')
 {
 OutPutC();          //显示记录表 
 }
 if(B=='Y' || B=='y')
 {
 OutPutX();          //显示解向量 
 }
    if( (A=='N' ||A=='n') && (B=='N' || B=='n') )
 {
 return 0;
 }


int u;
cin>>u;
return 0;
}
运行结果图:

(二)矩阵相乘算法对比

  两个矩阵相乘,改进的矩阵乘法,用分治法。

#include "stdafx.h"
#include <stdlib.h>
#include "iostream.h"
#include <time.h>

/*

┌       ┐ ┌       ┐ ┌       ┐
│C11 C12│ │A11 A12│ │B11 B12│
│C21 C22│=│A21 A22│*│B21 B22│
└       ┘ └       ┘ └       ┘

*/

const int N=700;
int Max_Value=4;

 int A11[N/2][N/2];
 int A12[N/2][N/2];
 int A21[N/2][N/2];
 int A22[N/2][N/2];
 int B11[N/2][N/2];
 int B12[N/2][N/2];
 int B21[N/2][N/2];
 int B22[N/2][N/2];
 int C11[N/2][N/2];
 int C12[N/2][N/2];
 int C21[N/2][N/2];
 int C22[N/2][N/2];

 //Temp
 int Temp1[N/2][N/2];
 int Temp2[N/2][N/2];

 int P[N/2][N/2];
 int Q[N/2][N/2];
 int R[N/2][N/2];
 int S[N/2][N/2];
 int T[N/2][N/2];
 int U[N/2][N/2];
 int V[N/2][N/2];

void GetValue(int M[N/2][N/2])        //小矩阵获取随机值
{
 int r,l;
 for( r=0;r<N/2;r++)
 {
  for( l=0;l<N/2;l++)
  {
  M[r][l]=rand()%Max_Value;
  }
 }
};

void Matrix_Mul(int M1[N/2][N/2],int M2[N/2][N/2],int MR[N/2][N/2]) //矩阵乘法 MR=M1×M2
{
 int i,r,l;

 for(r=0;r<N/2;r++)
 {
  for(l=0;l<N/2;l++)
  {
   MR[r][l]=0;
   for(i=0;i<N/2;i++)
   {
              MR[r][l]=MR[r][l]+M1[r][i]*M2[i][l];
   } 
  }
 }
};

void Matrix_Add(int M1[N/2][N/2],int M2[N/2][N/2],int MR[N/2][N/2])  //矩阵加法 MR=M1+M2
{
    int r=0,l=0;
 for( r=0;r<N/2;r++)
 {
  for( l=0;l<N/2;l++)
  {
        MR[r][l]=M1[r][l]+M2[r][l];
  }
 }
};

void Matrix_Sub(int M1[N/2][N/2],int M2[N/2][N/2],int MR[N/2][N/2])  //矩阵减法 MR=M1-M2
{
    int r=0,l=0;
 for( r=0;r<N/2;r++)
 {
  for( l=0;l<N/2;l++)
  {
        MR[r][l]=M1[r][l]-M2[r][l];
  }
 }
};

void OutPut(int M[N/2][N/2])    //输出小矩阵
{    int r,l;
 for( r=0;r<N/2;r++)
 {
  for( l=0;l<N/2;l++)
  {
      cout<<" "<<M[r][l];
   if(l==N/2-1)
   {cout<<endl;}
  }
 }
};

void OutPutAll(char w)        //输出大矩阵
{   int r,l;

    if(w=='A')
 {
  for( r=0;r<N/2;r++)
  {
   for( l=0;l<N;l++)
   {   if(l<N/2){cout<<" "<<A11[r][l];}
       if(l>=N/2 && l!=N){cout<<" "<<A12[r][l-N/2];}
    if(l==N-1){cout<<endl;}
   }
  }
  for(r=0;r<N/2;r++)
  {
   for( l=0;l<N;l++)
   {   if(l<N/2){cout<<" "<<A21[r][l];}
       if(l>=N/2 && l!=N){cout<<" "<<A22[r][l-N/2];}
    if(l==N-1){cout<<endl;}
   }
  }
 }

    if(w=='B')
 {
  for( r=0;r<N/2;r++)
  {
   for( l=0;l<N;l++)
   {   if(l<N/2){cout<<" "<<B11[r][l];}
       if(l>=N/2 && l!=N){cout<<" "<<B12[r][l-N/2];}
    if(l==N-1){cout<<endl;}
   }
  }
  for(r=0;r<N/2;r++)
  {
   for( l=0;l<N;l++)
   {   if(l<N/2){cout<<" "<<B21[r][l];}
       if(l>=N/2 && l!=N){cout<<" "<<B22[r][l-N/2];}
    if(l==N-1){cout<<endl;}
   }
  }
 }

 if(w=='C')
 {
  for( r=0;r<N/2;r++)
  {
   for( l=0;l<N;l++)
   {   if(l<N/2){cout<<" "<<C11[r][l];}
       if(l>=N/2 && l!=N){cout<<" "<<C12[r][l-N/2];}
    if(l==N-1){cout<<endl;}
   }
  }
  for(r=0;r<N/2;r++)
  {
   for( l=0;l<N;l++)
   {   if(l<N/2){cout<<" "<<C21[r][l];}
       if(l>=N/2 && l!=N){cout<<" "<<C22[r][l-N/2];}
    if(l==N-1){cout<<endl;}
   }
  }
 }

};

/
int main(int argc, char* argv[])
{
 cout<<"Strassen矩阵乘法"<<endl;
 cout<<"┌ ┐ ┌ ┐ ┌ ┐"<<endl;
    cout<<"│C│=│A│*│B│"<<endl;
 cout<<"└ ┘ └ ┘ └ ┘"<<endl;
 cout<<endl;
 cout<<"矩阵规模N*N="<<N<<"*"<<N<<endl<<endl;
    cout<<"运行....."<<endl;

    clock_t start, finish;
 double  duration1,duration2;
 ///get_value
    GetValue(A11);
 GetValue(A12);
 GetValue(A21);
 GetValue(A22);
 GetValue(B11);
 GetValue(B12);
 GetValue(B21);
 GetValue(B22);

 
    start = clock();
 //
    Matrix_Mul(A11,B11,Temp1);
 Matrix_Mul(A12,B21,Temp2);
 Matrix_Add(Temp1,Temp2,C11);

 Matrix_Mul(A11,B12,Temp1);
 Matrix_Mul(A12,B22,Temp2);
 Matrix_Add(Temp1,Temp2,C12);

 Matrix_Mul(A21,B11,Temp1);
 Matrix_Mul(A22,B21,Temp2);
 Matrix_Add(Temp1,Temp2,C21);

 Matrix_Mul(A21,B12,Temp1);
 Matrix_Mul(A22,B22,Temp2);
 Matrix_Add(Temp1,Temp2,C22);
   
 //
 finish = clock();
 duration1=finish-start;
 /
    start = clock();
 //
 Matrix_Add(A11,A22,Temp1);
 Matrix_Add(B11,B22,Temp2);
    Matrix_Mul(Temp1,Temp2,P);///P

 Matrix_Add(A21,A22,Temp1);
 Matrix_Mul(Temp1,B11,Q);  ///Q

 Matrix_Sub(B12,B22,Temp1);
 Matrix_Mul(A11,Temp1,R); ///R

 Matrix_Sub(B21,B11,Temp1);
 Matrix_Mul(A22,Temp1,S); ///S

 Matrix_Add(A11,A12,Temp1);
 Matrix_Mul(Temp1,B22,T); ///T

 Matrix_Sub(A21,A11,Temp1);
 Matrix_Add(B11,B12,Temp2);
 Matrix_Mul(Temp1,Temp2,U); ///U

 Matrix_Sub(A12,A22,Temp1);
 Matrix_Add(B21,B22,V);    //V

 Matrix_Add(P,S,Temp1);
 Matrix_Sub(Temp1,T,Temp2);
 Matrix_Add(Temp2,V,C11); //C11

 Matrix_Add(R,T,C12);    //C12

 Matrix_Add(Q,S,C21);    //C21

 Matrix_Add(P,R,Temp1);
 Matrix_Sub(Temp1,Q,Temp2);
 Matrix_Add(Temp2,U,C22); //C22

 //
 finish = clock();
 duration2=finish-start;
 /
/* OutPutAll('A');
 cout<<"*****************"<<endl;
 OutPutAll('B');
 cout<<"================="<<endl;
 OutPutAll('C');
*/ 
 cout<<"/n"<<"算法结果:"<<endl;
 cout<<"没改善算法用时:"<<duration1<<" ms"<<endl;
 cout<<"改善后算法用时:"<<duration2<<" ms"<<endl;

    int waiting;
    cin>>waiting;
 return 0;
}
运行结果图:

注:运行结果图的时间数值因不同机器而不同。但改善后的算法明显比没改善的算法所用时间少。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值