951 第8章

1、大整数乘法

算法思想参考网页博客:https://www.cnblogs.com/little-kwy/archive/2017/09/30/7613642.html
#include <stdlib.h>
#include <cstring>
#include <iostream>
using namespace std;

#define M 100

char sa[1000];
char sb[1000];

typedef struct _Node
{
    int s[M];
    int l;            //代表字符串的长度
    int c;
} Node,*pNode;

void cp(pNode src, pNode des, int st, int l)
{
    int i, j;
    for(i=st, j=0; i<st+l; i++, j++)
    {
        des->s[j] = src->s[i];
    }
    des->l = l;
    des->c = st + src->c;  //次幂

}

/*
分治法 大数乘法
X = A*10^n + B
Y = C*10^m + D
X*Y = A*C*10^(n+m) + A*D*10^n + B*C*10^m + B*D
*/

void add(pNode pa, pNode pb, pNode ans)
{
    int i,cc,k,palen,pblen,len;
    int ta, tb;
    pNode temp;
    if((pa->c<pb->c))   //保证Pa的次幂大
    {
        temp = pa;
        pa = pb;
        pb = temp;
    }
    ans->c = pb->c;
    cc = 0;
    palen=pa->l + pa->c;
    pblen=pb->l + pb->c;
    if(palen>pblen)
        len=palen;
    else
        len=pblen;
    k=pa->c - pb->c;
    for(i=0; i<len-ans->c; i++) //结果的长度最长为pa,pb之中的最大长度减去最低次幂
    {
        if(i<k)
            ta = 0;
        else
            ta = pa->s[i-k];//次幂高的补0,大于低的长度后与0进行计算
        if(i<pb->l)
            tb = pb->s[i];
        else
            tb = 0;
        if(i>=pa->l+k)
            ta = 0;
        ans->s[i] = (ta + tb + cc)%10;
        cc = (ta + tb + cc)/10;
    }
    if(cc)
        ans->s[i++] = cc;
    ans->l = i;
}

void mul(pNode pa, pNode pb, pNode ans)
{
    int i, cc, w;
    int ma = pa->l>>1, mb = pb->l>>1; //长度除2
    Node ah, al, bh, bl;
    Node t1, t2, t3, t4, z;
    pNode temp;

    if(!ma || !mb) //如果其中个数为1
    {
        if(!ma)   //如果a串的长度为1,pa,pb交换,pa的长度大于等于pb的长度
        {
            temp = pa;
            pa = pb;
            pb = temp;
        }
        ans->c = pa->c + pb->c;
        w = pb->s[0];
        cc = 0;     //此时的进位为c
        for(i=0; i < pa->l; i++)
        {
            ans->s[i] = (w*pa->s[i] + cc)%10;
            cc= (w*pa->s[i] + cc)/10;
        }
        if(cc)
            ans->s[i++] = cc; //如果到最后还有进位,则存入结果
        ans->l = i;          //记录结果的长度
        return;
    }
    //分治的核心
    cp(pa, &ah, ma, pa->l-ma);  //先分成4部分al,ah,bl,bh
    cp(pa, &al, 0, ma);
    cp(pb, &bh, mb, pb->l-mb);
    cp(pb, &bl, 0, mb);

    mul(&ah, &bh, &t1);     //分成4部分相乘
    mul(&ah, &bl, &t2);
    mul(&al, &bh, &t3);
    mul(&al, &bl, &t4);

    add(&t3, &t4, ans);
    add(&t2, ans, &z);
    add(&t1, &z, ans);
}

int main()
{
    Node ans,a,b;
    cout << "输入大整数 a:"<<endl;
    cin >> sa;
    cout << "输入大整数 b:"<<endl;
    cin >> sb;
    a.l=strlen(sa);//sa,sb以字符串进行处理
    b.l=strlen(sb);
    int z=0,i;
    for(i = a.l-1; i >= 0; i--)
        a.s[z++]=sa[i]-'0';             //倒向存储
    a.c=0;
    z=0;
    for(i = b.l-1; i >= 0; i--)
        b.s[z++] = sb[i]-'0';
    b.c = 0;
    mul(&a, &b, &ans);
    cout << "最终结果为:";
    for(i = ans.l-1; i >= 0; i--)
        cout << ans.s[i];         //ans用来存储结果,倒向存储
    cout << endl;
    return 0;
}

2、矩阵连乘

算法思想,网页博客连接:https://blog.csdn.net/x_xhuashui/article/details/81903558
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int msize = 100;
int p[msize];
int m[msize][msize];
int s[msize][msize];
int n;

void matrixchain()
{
    int i,j,r,k;
    memset(m,0,sizeof(m));
    memset(s,0,sizeof(s));
    for(r = 2; r <= n; r++)         //不同规模的子问题
    {
        for(i = 1; i <= n-r+1; i++)
        {
           j = i + r - 1;
           m[i][j] = m[i+1][j] + p[i-1] * p[i] * p[j];  //决策为k=i的乘法次数
           s[i][j] = i;                     //子问题的最优策略是i;
           for(k = i+1; k < j; k++) //对从i到j的所有决策,求最优值,记录最优策略
            {
                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 print(int i,int j)
{
    if( i == j )
    {
       cout <<"A[" << i << "]";
       return ;
    }
    cout << "(";
    print(i,s[i][j]);
    print(s[i][j]+1,j);
    cout << ")";
}
int main()
{
    cout << "请输入矩阵的个数 n:";
    cin >> n;
    int i ,j;
    cout << "请依次输入每个矩阵的行数和最后一个矩阵的列数:";
    for (i = 0; i <= n; i++ )
        cin >> p[i];
    matrixchain();
    print(1,n);
    cout << endl;
    /*用于测试
    for (i = 1; i <= n; i++ )
        {
          for (j = i; j <= n; j++ )
            cout << m[i][j]<<"  " ;
          cout << endl;
        }
     for (i = 1; i <= n; i++ )
        {
          for (j = i; j <= n; j++ )
            cout << s[i][j]<<"  " ;
          cout << endl;
        }
    cout << endl;
    */
    cout << "最小计算量的值为 " << m[1][n] << endl;
}

3、棋盘覆盖问题

算法思想参考网页博客连接:https://blog.csdn.net/qq_30268545/article/details/80600064
#include <stdio.h>
#include <stdlib.h>
#include<string.h>

int nCount = 0;
int Matrix[100][100];

void chessBoard(int tr, int tc, int dr, int dc, int size);

int main()
{
    int size, r, c, row, col;
    memset(Matrix, 0, sizeof(Matrix));
    scanf_s("%d", &size);
    scanf_s("%d%d", &row, &col);
    chessBoard(0, 0, row, col, size);

    for (r = 0; r < size; r++)
    {
        for (c = 0; c < size; c++)
        {
            printf("%2d ", Matrix[r][c]);
        }
        printf("\n");
    }

    return 0;
}

void chessBoard(int tr, int tc, int dr, int dc, int size)
{
    int s, t;
    if (1 == size) return;
    s = size / 2;
    t = ++nCount;
    if (dr < tr + s && dc < tc + s)
    {
        chessBoard(tr, tc, dr, dc, s);
    }
    else
    {
        Matrix[tr + s - 1][tc + s - 1] = t;
        chessBoard(tr, tc, tr + s - 1, tc + s - 1, s);
    }

    if (dr < tr + s && dc >= tc + s)
    {
        chessBoard(tr, tc + s, dr, dc, s);
    }
    else
    {
        Matrix[tr + s - 1][tc + s] = t;
        chessBoard(tr, tc + s, tr + s - 1, tc + s, s);
    }
    if (dr >= tr + s && dc < tc + s)
    {
        chessBoard(tr + s, tc, dr, dc, s);
    }
    else
    {
        Matrix[tr + s][tc + s - 1] = t;
        chessBoard(tr + s, tc, tr + s, tc + s - 1, s);
    }
    if (dr >= tr + s && dc >= tc + s)
    {
        chessBoard(tr + s, tc + s, dr, dc, s);
    }
    else
    {
        Matrix[tr + s][tc + s] = t;
        chessBoard(tr + s, tc + s, tr + s, tc + s, s);
    }

}

4、求平面中点之间的最短距离

算法思想参考网页博客连接:https://blog.csdn.net/hnu2012/article/details/70894678
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct point
{
	double x;
	double y;
};
bool sortBy_x(point& point1, point& point2) //根据x坐标从小到大排序
{
	if (point1.x == point2.x)
		return point1.y < point2.y;
	return point1.x < point2.x;
}
bool sortBy_y(point& point1, point& point2)    //根据纵坐标从小到大排序
{
	return point1.y < point2.y;
}
double getDistance(point& point1, point& point2)
{
	double dis_x = point1.x - point2.x;
	double dis_y = point1.y - point2.y;
	return sqrt(dis_x*dis_x+dis_y*dis_y);
}
double getMin(vector<point>& vec, int low, int high)
{
	if (high - low == 1)    //2个结点
	{
		return getDistance(vec[low], vec[low + 1]);
	}	
	else if (high - low == 2)        //3个结点
	{
		double dist1= getDistance(vec[low], vec[low + 1]);
		double dist2 = getDistance(vec[low], vec[low + 2]);
		double dist3 = getDistance(vec[low+1], vec[low + 2]);
		return min(min(dist1, dist2), dist3);
	}
	else
	{
		int mid = (low + high) / 2;
		double left_min = getMin(vec, low, mid);
		double right_min = getMin(vec, mid + 1, high);
		double d = min(left_min, right_min);
		vector<point> res;
		res.erase(res.begin(), res.end());  
		int i, j,k=0;
		for (i = low; i <= high; i++)        //遍历一遍数组,得到与横坐标与  中点横坐标距离在d以内的点
		{
			if (fabs(vec[i].x - vec[mid].x) < d)
				res.push_back(vec[i]);
		}
		sort(res.begin(),res.end(),sortBy_y);      //根据纵坐标从小到大排序
		for (i = 0; i < res.size() - 1; i++)
		{
			for (j = i + 1; j < res.size(); j++)  //求距离的点 为与i纵坐标的距离在d以内
			{
				if (res[j].y - res[i].y >= d)
					break;
				double dp = getDistance(res[i], res[j]);
				if (dp < d)
				{
					d = dp;
				}
			}
		}
		return d;
	}
}
int main()
{
	int i, j, n;
	cin >> n;     //输入点的个数
	vector<point> vec;
	for (i = 0; i < n; i++)
	{
		point point1;
		cin >> point1.x >> point1.y;
		vec.push_back(point1);
	}
	sort(vec.begin(), vec.end(), sortBy_x);
	cout << "所有点之间的最短距离为:" << getMin(vec, 0, vec.size() - 1) << endl;  
	system("pause");
	return 0;
}

5、比赛日程表

算法思想参考网页博客:https://blog.csdn.net/hnu2012/article/details/70894678
#include <iostream>     
#include <math.h> 
using namespace std;   

void Table(int k,int n,int **a); 
void input(int &k); 
void output(int **a,int n); 

int main() 
{ 
    int k; 
    input(k); 

    int n=1; 
    //n=2k(k>=1)个选手参加比赛 
    for(int i=1; i<=k; i++) 
        n *= 2; 

    //根据n动态分配二维数组a 
    int **a = new int *[n+1]; 
    for(i=0;i<=n;i++) 
    { 
        a[i] = new int[n+1]; 
    } 


    Table(k,n,a); 

    cout<<"循环赛事日程表为:"<<endl; 
    output(a,n); 

    //释放空间 
    for(i=0;i<=n;i++) 
    { 
        delete[] a[i]; 
    } 
    delete[] a; 

    return 0; 
} 

void input(int &k) 
{ 
    cout<<"请输入k值:"<<endl; 
    cin>>k; 
} 

void output(int **a,int n) 
{ 
    for(int i=1; i<=n; i++) 
    { 
        for(int j=1; j<=n; j++) 
        { 
            cout<<a[i][j]<<" "; 
        } 
        cout<<endl; 
    } 
} 

void Table(int k,int n,int **a) 
{ 
    for(int i=1; i<=n; i++) 
        a[1][i]=i;//设置日程表第一行 

    int m = 1;//每次填充时,起始填充位置 
    for(int s=1; s<=k; s++) 
    { 
        n /= 2;//分割表格  
        for(int t=1; t<=n; t++) 
        { 
            for(int i=m+1; i<=2*m; i++)//控制行 
            { 
                for(int j=m+1; j<=2*m; j++)//控制列 
                { 
                    a[i][j+(t-1)*m*2] = a[i-m][j+(t-1)*m*2-m];//右下角等于左上角的值 
                    a[i][j+(t-1)*m*2-m] = a[i-m][j+(t-1)*m*2];//左下角等于右上角的值 
                 } 

               } 
            } 
        m *= 2; 
    } 
}

6、最长公共子序列

参考网页博客:https://www.cnblogs.com/wkfvawl/p/9362287.html
#include <iostream>
#include<cstring>
using namespace std;
const int N=1002;
int c[N][N],b[N][N];
char s1[N],s2[N];
int len1,len2;

void LCSL()
{
    int i,j;
    for(i = 1;i <= len1;i++)//控制s1序列不同的子问题
      for(j = 1;j <= len2;j++)//控制s2序列不同的子问题
      {
        if(s1[i-1]==s2[j-1])
        {
            c[i][j] = c[i-1][j-1]+1;//如果当前字符相同,则公共子序列的长度为该字符前的最长公共序列+1
            b[i][j] = 1;
        }
        else
        {
             if(c[i][j-1]>=c[i-1][j])
            {
                c[i][j] = c[i][j-1];
                b[i][j] = 2;
            }
            else
            {
                c[i][j] = c[i-1][j];
                b[i][j] = 3;
            }
        }
     }
}

void print(int i, int j)//根据记录下来的信息构造最长公共子序列(从b[i][j]开始递推)
{
    if(i==0 || j==0) return;
    if(b[i][j]==1)
    {
        print(i-1,j-1);
        cout<<s1[i-1];
    }
    else if(b[i][j]==2)
            print(i,j-1);
         else
            print(i-1,j);
}

int main()
{
    int i,j;
    cout << "输入字符串s1:"<<endl;
    cin >> s1;
    cout << "输入字符串s2:"<<endl;
    cin >> s2;
    len1 = strlen(s1);//计算两个字符串的长度
    len2 = strlen(s2);
    for(i = 0;i <= len1;i++)
    {
        c[i][0]=0;//初始化第一列为0
    }
    for(j = 0;j<= len2;j++)
    {
        c[0][j]=0;//初始化第一行为0
    }
    LCSL();
    cout << "s1和s2的最长公共子序列长度是:"<<c[len1][len2]<<endl;
    cout << "s1和s2的最长公共子序列是:";
    print(len1,len2);
    cout<<endl;
    // /*用于测试
    cout<<"c[i][j]数组:"<<endl;
    for(i = 0;i <= len1;i++)
    {
        for(j = 0;j <= len2;j++)
          cout <<"  "<<c[i][j];
        cout<<endl;
    }
    cout<<"b[i][j]数组:"<<endl;
    for(i = 0;i <= len1;i++)
    {
        for(j = 0;j <= len2;j++)
          cout <<"  "<<b[i][j];
        cout<<endl;
    }
    // */用于测试
    return 0;
}

7、最大子段和问题

参考网页博客:https://blog.csdn.net/ailunlee/article/details/80095759
#include<iostream>
using namespace std;

int MaxSubsequenceSum(const int A[], int n)
{
    int tempSum = 0;
    int maxSum = 0;
    for (int j = 0;j < n;j++)   // 子问题后边界
    {
        tempSum = (tempSum + A[j]) > A[j] ? (tempSum + A[j]) : A[j];
        if (tempSum > maxSum)   // 更新最大和
            maxSum = tempSum;

    }
    return maxSum;
}

int main()
{
    const int a[] = { 4, -3, 5, -2, -1, 2, 6, -2 };
    int maxSubSum = MaxSubsequenceSum(a, 8);
    cout << "The max subsequence sum of a is: " << maxSubSum << endl;
    system("pause");
    return 0;
}

8、最优三角剖分

参考网页博客:https://bbs.csdn.net/topics/180000337
#include "iostream.h"
#include "math.h"
typedef struct 
{
    double x;
    double y;
}point;
double distanse(point x,point y)
{
    double dis= (y.y-x.y)*(y.y-x.y)+(y.x-x.x)*(y.x-x.x);
    return sqrt(dis);
}
int main()
{
    int n;cin>>n;
    point *v =new point[n];
    for(int i=0;i<n;i++)
        cin>>v[i].x>>v[i].y;
 
    int j,k,d;
    double **t=new double*[n];
    for(i=0;i<n;i++)
    {
        t[i]=new double[n];
        t[i][i]=0;
    }
    double temp;
    for(d=1;d<n;d++)
    {
        for(i=1;i<n-d;i++)
        {
            j=i+d;
            t[i][j]=32767;
            for(k=i;k<j;k++)
            {
                if(k==i&&j-i!=n-2)
                    temp=distanse(v[i-1],v[j])+t[i][k]+t[k+1][j];
                else if(k==i&&j-1==n-2)
                    temp=t[i][k]+t[k+1][j];
                else
                    temp=distanse(v[i-1],v[k])+distanse(v[i-1],v[j])+t[i][k]+t[k+1][j];
                if(temp<t[i][j])
                    t[i][j]=temp;
            }
        }
    }
    cout<<t[1][n-1];
    return 0;
}
/*
5
0 0 2 0 2 2 1 3 0 2
*/

9、多边形游戏问题

参考网页连接:https://blog.csdn.net/liufeng_king/article/details/8641118
#include "stdafx.h"
#include <iostream> 
using namespace std; 
 
#define NMAX 100
int N,m[NMAX+1][NMAX+1][2],v[NMAX+1]; 
char op[NMAX+1];
 
void MinMax(int n,int i,int s,int j,int &minf,int &maxf);
int PloyMax(int n,int& p);
 
int main() 
{  
	int p;
	cout<<"请输入多边形顶点数:"<<endl;
	cin>>N;
	for(int i=1; i<=N; i++)
	{
		cout<<"请输入多边形顶点"<<i<<"数值:"<<endl;
		cin>>v[i];  
		m[i][1][0]=v[i];  
		m[i][1][1]=v[i]; 
		cout<<"请输入多边形边"<<i<<"运算符:"<<endl;
		cin>>op[i];   
	} 
	cout<<"多边形游戏首次删除第"<<p<<"条边,结果为:"<<PloyMax(N,p)<<endl; 
	return 0;
}
 
void MinMax(int n,int i,int s,int j,int &minf,int &maxf)
{ 
	int e[5];
	int a=m[i][s][0],b=m[i][s][1];
	int r=(i+s-1)%n+1;//多边形的实际顶点编号
	int c=m[r][j-s][0],d=m[r][j-s][1];
 
	if(op[r-1]=='+')
	{   
		minf=a+c;
		maxf=b+d;
	} 
	else
	{   
		e[1]=a*c;
		e[2]=a*d;
		e[3]=b*c; 
		e[4]=d*b;  
		minf=e[1];  
		maxf=e[1]; 
 
		for(int r=2;r<N;r++) 
		{   
			if(minf>e[r])minf=e[r];
			if(maxf<e[r])maxf=e[r];
		}
	}
}
 
int PloyMax(int n,int& p)
{ 
	int minf,maxf;
	for(int j=2;j<=n;j++) //迭代链的长度
	{
		for(int i=1;i<=n;i++)//迭代首次删掉第i条边
		{
			for(int s=1 ;s<j;s++) //迭代断开位置
			{    
				MinMax(n,i,s,j,minf,maxf);
				if(m[i][j][0]>minf) m[i][j][0]=minf; 
				if(m[i][j][1]<maxf) m[i][j][1]=maxf;
			}  
		}
	}
 
	int temp=m[1][n][1]; 
	p=1;
 
	for(int i=2 ;i<=n; i++)  
	{    
		if(temp<m[i][n][1]) 
		{
			temp=m[i][n][1];
			p=i;
		}
	}                  
	return temp;
}

10、电路布线(动态规划问题)

详解链接:https://www.cnblogs.com/wkfvawl/p/11660698.html
#include <iostream>
using namespace std;

const int N = 10;

void MNS(int C[],int n,int **size);
void Traceback(int C[],int **size,int n,int Net[],int& m);

int main()
{
    int c[] = {0,8,7,4,2,5,1,9,3,10,6};//下标从1开始
    int **size = new int *[N+1];

    for(int i=0; i<=N; i++)
    {
        size[i] = new int[N+1];
    }

    MNS(c,N,size);

    cout<<"电路布线最大不相交连线数目为:"<<size[N][N]<<endl;

    int Net[N],m;
    Traceback(c,size,N,Net,m);

    cout<<"最大不相交连线分别为:"<<endl;
    for(int i=m-1; i>=0; i--)
    {
        cout<<"("<<Net[i]<<","<<c[Net[i]]<<") ";
    }
    cout<<endl;
    return 0;
}

void MNS(int C[],int n,int **size)
{
    for(int j=0;j<C[1];j++)
    {
        size[1][j]=0;
    }

    for(int j=C[1]; j<=n; j++)
    {
        size[1][j]=1;
    }

    for(int i=2; i<n; i++)
    {
        for(int j=0; j<C[i]; j++)
        {
            size[i][j]=size[i-1][j];//当i<c[i]的情形
        }
        for(int j=C[i]; j<=n; j++)
        {
            //当j>=c[i]时,考虑(i,c[i])是否属于MNS(i,j)的两种情况
            size[i][j]=max(size[i-1][j],size[i-1][C[i]-1]+1);
        }
    }
    size[n][n]=max(size[n-1][n],size[n-1][C[n]-1]+1);
}

void Traceback(int C[],int **size,int n,int Net[],int& m)
{
    int j=n;
    m=0;
    for(int i=n;i>1;i--)
    {
        if(size[i][j]!=size[i-1][j])//此时,(i,c[i])是最大不相交子集的一条边
        {
            Net[m++]=i;
            j=C[i]-1;//更新扩展连线柱区间
        }
    }
    if(j>=C[1])//处理i=1的情形
    {
        Net[m++]=1;
    }
}

11、流水作业调度问题

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int MX=10000+5;
int n,bestf,f1,f2;//f1在第一台机器上加工的完成时间,f2在第二台机器上加工的完成时间
int x[MX],bestx[MX];
struct node
{
    int x,y;//作业在第一台机器上的加工时间x和第二台机器上的加工时间y
}T[MX];
void Backtrack(int t)
{
    if(t>n)
    {
        for(int i=1;i<=n;i++) //记录最优排列
           bestx[i]=x[i] ;
        bestf=f2;   // 更新最优值
        return ;
    }
    for(int i=t;i<=n;i++)  // 枚举
    {
        f1+=T[x[i]].x;
        int temp=f2;
        f2=max(f1,f2)+T[x[i]].y;
        if(f2<bestf)  //限界条件
        {
            swap(x[t] ,x[i]);  // 交换
            Backtrack(t+1);          // 继续深搜
            swap(x[t],x[i]);  // 复位,反操作
        }
        f1-=T[x[i]].x ;
        f2=temp ;
    }
}
int main()
{
    cout<<"请输入作业的个数 n:";
    cin>>n;
    cout<<"请依次输入每个作业在第一台机器上的加工时间x和第二台机器上的加工时间y:";
    for(int i=1;i<=n;i++)
    {
        cin>>T[i].x>>T[i].y;
        x[i]=i;
    }
    bestf=INF;    // 初始化
    f1=f2=0;
    memset(bestx,0,sizeof(bestx));
    Backtrack(1);         // 深搜排列树
    cout<<"最优的作业加工顺序为:";
    for(int i=1;i<=n;i++) //输出最优加工顺序
       cout<<bestx[i]<<" ";
    cout<<endl;
    cout<<"最优的作业加工的时间为:";
    cout<<bestf<<endl;
    return 0 ;
}

12、01背包问题

网页参考连接:https://www.cnblogs.com/rainxbow/p/9713749.html
#include <iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 10005
#define M 105
int c[M][maxn];//c[i][j] 表示前i个物品放入容量为j购物车获得的最大价值
int w[M],v[M];//w[i] 表示第i个物品的重量,v[i] 表示第i个物品的价值
int x[M];  //x[i]表示第i个物品是否放入购物车
int main(){
    int i,j,n,W;//n表示n个物品,W表示购物车的容量
    cout << "请输入物品的个数 n:";
    cin >> n;
    cout << "请输入购物车的容量W:";
    cin >> W;
    cout << "请依次输入每个物品的重量w和价值v,用空格分开:";
    for(i=1;i<=n;i++)
        cin>>w[i]>>v[i];
    for(i=1;i<=n;i++)//初始化第0列为0
        c[i][0]=0;
    for(j=1;j<=W;j++)//初始化第0行为0
        c[0][j]=0;
    for(i=1;i<= n;i++)//计算c[i][j]
        for(j=1;j<=W;j++)
            if(j<w[i])  //当物品的重量大于购物车的容量,则不放此物品
                c[i][j] = c[i-1][j];
            else    //否则比较此物品放与不放是否能使得购物车内的价值最大
                c[i][j] = max(c[i-1][j],c[i-1][j-w[i]] + v[i]);
    cout<<"装入购物车的最大价值为:"<<c[n][W]<<endl;

    //用于测试
    for (i=1; i<=n; i++ )
    {
        for (j=1; j<=W; j++ )
          cout << c[i][j]<<"\t" ;
        cout << endl;
    }
    cout << endl;

    //逆向构造最优解
    j=W;
    for(i=n;i>0;i--)
        if(c[i][j]>c[i-1][j])
        {
            x[i]=1;
            j-=w[i];
        }
        else
            x[i]=0;
    cout<<"装入购物车的物品序号为:";
    for(i=1;i<=n;i++)
        if(x[i]==1)
           cout<<i<<"  ";
    return 0;
}

13、背包问题

#include <iostream> 
#include <algorithm> 
#include <bitset> 
using namespace std; 
struct node 
{ 
    int id; 
    int val; 
}; 
node box[2005]; 
int n,c; 
bool operator <(const node &a,const node &b) 
{ 
    return a.val<b.val; 
} 
void greedySelect() 
{ 
    sort(box,box+n);               
    bitset<2005> b; 
    b.reset(); 
    for(int i=0;i<n;i++) 
     if(box[i].val <= c) 
     { 
          b[box[i].id]=1; 
          c-=box[i].val; 
     } 
     else break; 
     cout<<b.count()<<endl; 
} 
int main() 
{ 
    while(cin>>n>>c) 
    { 
        for(int i=0;i<n;i++) 
        { 
            box[i].id=i; 
            cin>>box[i].val; 
        } 
        greedySelect();  
    } 
    return 0; 
}

14、多机调度问题

#include <iostream> 
using namespace std; 
void Greedy(int t[],int n,int m);
 int main() { 
int n=7,m=3,t[]={2,14,4,16,6,5,3};//待分配的工作 
Greedy(t,n,m);
 return 0; } 
void Greedy(int t[],int n,int m) 
{ int flagn,flagm; int M[]={0,0,0,0,0,0,0,0};
 for(int i=0;i<n;i++) 
{ int max=0,min=10000;
 flagn=0; 
flagm=0; 
for(int j=0;j<n;j++)//选择时间最多的工作 
{ if(max<t[j]) { max=t[j]; flagn=j; } } 
for(j=0;j<m;j++)//选择工作量最小的机器 
{
 if(M[flagm]>M[j])
 {flagm=j;} 
} 
M[flagm]=M[flagm]+t[flagn]; t[flagn]=0; //被选择过的机器时间调为 0
 cout<<flagn<<"work "<<flagm<<"machine"<<endl; } }
posted @ 2020-12-13 16:32  Alex-jzw  阅读(125)  评论(0)    收藏  举报