分治法:归并排序、快速排序、最大子段和 、最近点对问题
贪心法:多级调度问题、活动安排问题、背包问题
动态规划法:、最大子段和、近似串匹配、最优二叉树 、最长公共子序列、0-1背包问题、多段图最短路径
*******************************************************************
分治法
1、归并排序
// Note:Your choice is C++ IDE
//归并排序(分治法)
#include<iostream>
using namespace std;
//合并两个有序子序列
void Merge( int r1[ ] , int r[ ], int s, intm, int t)
{
inti,j,k;
i=s; j=m+1; k=s;
while (i<=m&& j<=t) {
if (r[i]<=r[j])r1[k++]=r[i++];
else r1[k++]=r[j++];
}
if(i<=m)
while (i<=m)
r1[k++]=r[i++];
else
while (j<=t)
r1[k++]=r[j++];
for( i=s; i<=t; i++)
r[i]=r1[i]; //r[]:第二个数组是合并排序后的序列
}
//分治法归并排序
void MergeSort(int r[ ], int r1[ ], int s, intt) {
intm;
if (s==t) r1[s]=r[s];
else {
m=(s+t)/2;
MergeSort(r, r1, s, m); //归并排序前半个子序列
MergeSort(r, r1, m+1, t); //归并排序后半个子序列
Merge(r, r1, s, m, t); //合并两个已排序的子序列
}
}
int main()
{
intr[256],r1[256];
intt;
cin>>t;
for(inti=1; i<=t; i++)
cin>>r[i];
ints=1;
MergeSort( r, r1, s, t) ;
for(i=1; i<=t; i++)
cout<<r1[i]<<"";
return0;
}
===================================
2、快速排序
#include<iostream.h>
void Swap(int a[], int m, int n){
inttemp;
temp=a[m];
a[m]= a[n];
a[n] =temp;
}
int Partition(int r[ ], int first, intend)
{
int i=first ,j=end; //初始化
while(i<j)
{
while (i<j&& r[i]<= r[j]) j--; //右侧扫描
if (i<j){
Swap(r,i,j); //将较小记录交换到前面
i++;
}
while (i<j&& r[i]<= r[j]) i++; //左侧扫描
if (i<j) {
Swap(r,i,j); //将较大记录交换到后面
j--;
}
}
return i; // i为轴值记录的最终位置
}
void QuickSort(int r[ ], int first, intend)
{
if(first<end) {
int pivot=Partition(r, first,end);
QuickSort(r, first,pivot-1);
QuickSort(r, pivot+1,end);
}
}
void main(){
int n,r[100],i;
cin>>n;
for( i=1;i<=n; i++)
cin>>r[i];
QuickSort(r,0,n);
for( i=1;i<=n; i++)
cout<<r[i]<<"";
}
===========================================
3、最大子段和
一、蛮力法
#include<iostream.h>
int BFMaxSum(int a[ ], int n){
int sum=0, i,j;
for(i=0;i<n; i++){
int s1=0; //s1的复原为零很重要;
for(j=i;j<n; j++){
s1 += a[j];
if (s1 > sum) sum = s1;
//cout<<j<<""<<sum<<""<<endl; //这是自己的调试过程
}
}
return sum;
}
void main(){
int a[100];
int i,n;
cout<<"请输入整数个数:";
cin>>n;
cout<<"请输入这"<<n<<"个整数所组成的序列:";
for(i=0;i<n; i++)
cin>> a[i];
int rs=BFMaxSum( a, n);
cout<<"该序列的最大字段和为:"<<rs<<endl;
}
二、分治法
#include<iostream.h>
int MaxSubSum(int a[ ], int left, int right){
int sum=0,i,j;
//如果序列长度为1,直接求解
if (left==right) {
if(a[left]>0) sum=a[left];
else sum=0;
}
else {
int center=(left+right)/2; //划分
intleftsum=MaxSubSum(a, left, center);
intrightsum=MaxSubSum(a, center+1, right);
//以下对应情况③,先求解s1
int s1=0,lefts=0;
for (i=center;i>=left; i--){
lefts+=a[i];
if (lefts>s1) s1=lefts;
}
int s2=0, rights=0; //再求解s2
for (j=center+1; j<=right;j++){
rights+=a[j];
if (rights>s2) s2=rights;
}
sum=s1+s2; //计算情况③的最大子段和
//合并,在sum、leftsum和rightsum中取较大者
if(sum<leftsum) sum=leftsum;
if(sum<rightsum) sum=rightsum;
}
returnsum;
}
void main(){
int a[100];
int i,n;
cout<<"请输入整数个数:";
cin>>n;
cout<<"请输入这"<<n<<"个整数所组成的序列:";
for(i=0;i<n; i++)
cin>> a[i];
int rs=MaxSubSum( a, 0, n-1);
cout<<"该序列的最大字段和为:"<<rs<<endl;
}
三、动态规划法
参考动态规划法中的。。
==============================================================
4、最近点对问题
一、参考
#define inf 9999999
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
struct point
{
double x, y;
}p[100005];
int a[100005]; //保存筛选的坐标点的索引
bool cmpx( point a , point b){ //结构体数组的排序//这里用的是下标索引
returna.x < b.x;
}
bool cmpy(int a , int b){
returnp[a].y < p[b].y;
}
double dis(point a , point b){
returnsqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
double min(double a , double b){
return a< b ? a : b;
}
double closest(int low , int high)
{
if(low==high)
returninf; //1、如果n=1,返回无限大值
int mid= (low + high)>>1; //除2操作可为右移一位; 2、得到中点数
doubleans = min( closest(low , mid) , closest(mid + 1 , high) ); //分治法
int i ,j , cnt = 0;
for(i =low ; i <= high ; ++i)
{
if(p[i].x >=p[mid].x - ans && p[i].x<= p[mid].x + ans)
a[cnt++] = i; //a[]数组记录点的坐标
}
sort(a , a + cnt , cmpy);
for(i =0 ; i < cnt ; ++i)
{
for(j = i+1 ; j<cnt&&j<=i+7 ;++j)
{
if(p[a[j]].y - p[a[i]].y >=ans)
break;
ans = min(ans , dis(p[a[i]] , p[a[j]]));
}
}
returnans;
}
int main()
{
inti,n;
while(scanf("%d",&n) != EOF)
{
if(!n)
break;
for(i = 0 ; i <n ; ++i)
scanf("%lf%lf",&p[i].x,&p[i].y);
sort(p , p + n , cmpx);
printf("%.2lf\n",closest(0 , n- 1));
}
return0;
}
二、蛮力法
#include<iostream>
using namespace std;
int main()
{
intn,i,j,x[256],y[256],index1=0,index2=0;
intd,min;
cin>>n;
for(i=0;i<n; i++)
cin>>x[i]>>y[i];
//先假定第一个和第二个点间的距离为所有点对的距离的最小值
min=(x[1]-x[2])*(x[1]-x[2])+(y[1]-y[2])*(y[1]-y[2]);
//为了避免同一对点计算两次,只考虑i<j的那些点对
for(i=0;i<n; i++)
for(j=i+1; j<n; j++){
//d为点对间的距离,运用打擂台的思想
d=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
//index1,index2记录点对
//min即为最后所有点对间的最小距离值
if(d<=min){
min=d;
index1=i+1;
index2=j+1;
}
}
cout<<"距离最短的两个点是第"<<index1<<"个点与第"<<index2<<"个点"<<endl;
cout<<"最近的距离的平方是"<<min<<endl;
return0;
}
三、分治法
与最大子段和的分治法很相像
#include<iostream>
//#include<cstdlib>
#include<cmath>
#define Max 10000000
using namespace std;
int min(int a,int b){ //求两数最小值
return (a>=b ) ? b : a;
}
int abs(int a){ //绝对值
return a>0? a: -a;
}
int dis(int x1, int y1, int x2, int y2){//距离
cout<<"计算的距离:"<<x1<<","<<y1<<"与"<<x2<<","<<y2<<endl;
return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}
int ClosePoints(int n,int s[][2]){ //用二维数组存放点的横纵坐标
//1、点的个数应该大于2
if (n < 2) return Max;
if(n==2) returndis(s[0][0],s[0][1],s[1][0],s[1][1]);
intm=0,i,j;
ints1[256][2],s2[256][2];
//2、m为s中x坐标的中位数
sort(s,s+n);
m=(s[0]+s[n-1])/2;
// for(i=0;i<n; i++){
// m += s[i][0];
//cout<<"s:"<<s[i][0]<<""<<s[i][1]<<endl;
//}
//m /=n;
//3、构造s1和s2, 使得s1中的x坐标小于m,s2中点的坐标大于m
int k=0;
int h=0;
for(i=0;i<n; i++)
{
if(s[i][0]<m)
{
s1[h][0]=s[i][0];
s1[h++][1]=s[i][1];
}
else
{
s2[k][0]=s[i][0];
s2[k++][1]=s[i][1];
}
}
//4、分治法
cout<<endl;
int d1=ClosePoints(h,s1);
int d2=ClosePoints(k,s2);
//5、使得d为S1中的最近距离d1和S2中的最近距离d2的最小值
int d=min(d1,d2);
//6、构造p1和p2,使得p1是s1中点的x坐标与m的距离小于d的点集,p2是s2中点的x坐标与m的距离小于d的点集
int c=0,f=0;
int p1[256][2],p2[256][2];
for(i=0; i<h; i++)
{
if(abs(s1[i][0]-m)<d){
for(j=0; j<2; j++)
p1[c++][j]=s1[i][j];
}
//输出s1数组
cout<<"s1:"<<s1[i][0]<<""<<s1[i][1]<<endl;
}
for(i=0; i<k; i++)
{
if(abs(s2[i][0]-m)<d){
for(j=0; j<2; j++)
p2[f++][j]=s2[i][j];
}
//输出s2数组
cout<<"s2:"<<s2[i][0]<<""<<s2[i][1]<<endl;
}
//7、将p1和p2中点的按y坐标升序排列
int temp;
for(i=0; i<c; i++)
for(j=1; j<c-i; j++){
if(p1[j-1][1]>p1[j][1]){
temp=p1[j][1];
p1[j][1] = p1[j-1][1];
p1[j+1][1] = temp;
temp=p1[j][0];
p1[j][0] = p1[j-1][0];
p1[j+1][0] = temp;
}
}
//输出排序后的p1数组
for(i=0; i<c; i++)
cout<<"p1:"<<p1[i][0]<<""<<p1[i][1]<<endl;
for(i=0; i<f; i++)
for(j=1; j<f-i; j++){
if(p2[j-1][1]>p2[j][1]){
temp=p2[j][1];
p2[j][1] = p2[j-1][1];
p2[j+1][1] = temp;
temp=p2[j][0];
p2[j][0] = p2[j-1][0];
p2[j+1][0] = temp;
}
}
//输出排序后的p2数组
for(i=0; i<f; i++)
cout<<"p2:"<<p2[i][0]<<""<<p2[i][1]<<endl;
cout<<endl;
//8、对p1中的每一个点p,在p2中查找与点p的y坐标小于d的点,并求出其中的最小距离dmin
int dmin=0;
if(c!=0 &&f!=0)
dmin=dis(p1[0][0],p1[0][1],p2[0][0],p2[0][1]);
else return min(d,Max);
for(i=0; i<c; i++){
for(j=0; j<f; j++){
if( abs(p1[i][1]-p2[j][1])<d){
dmin = dis(p1[i][0], p1[i][1], p2[j][0],p2[j][1]);
d=dmin;
}
}
}
//9、返回最小值d
returnmin(d,dmin);
}
int main()
{
int s[256][2];
int n,i,j;
cin>>n;
//依次输入n个点的x,y坐标
for(i=0;i<n; i++)
for(j=0; j<2; j++)
cin>>s[i][j];
int rd=ClosePoints(n,s);
cout<<"最近点对间的距离为:";
cout<<sqrt(rd)<<endl;
return0;
}
==============================
******************************************
贪心法
1、多级调度问题
#include<iostream>
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct Data
{
intdata;
intindex;
};
Data t[100];
Data d[100];
bool cmp(Data a,Data b){ //实现结构体数组按照data项进行从大到小排序
return a.data > b.data ;
}
int sortmin(Data d[], intn){ //寻找d[]数组中的最小值
int i,indexs=0;
for(i=0; i<n; i++){
if(d[i].data < d[indexs].data)
indexs=i;
}
return indexs;
}
void duoji(Data t[], int n,int m){
int i, S[100][100], p[100] , h[100];
Data d[100];
memset(h,0,sizeof(h));
sort(t,t+n,cmp); //结构体的排序
cout<<endl<<"排序后的作业序号为:";
for(i=0; i<n; i++){
p[i]=t[i].index; //1、将t[]排序后,按照从大到小将作业号存储在p[]数组中
cout<<p[i]+1<<"";
}
cout<<endl;
for(i=0; i<m; i++){ //2、初始化d[]数组,d[]数组记录的是m台机器的空闲时间
d[i].data=0;
d[i].index=i;
}
if(n<m){ //A、当作业数n < 机器数m的情况
for(i=0; i<n; i++){ //记录第一次的分配
S[i][0]=p[i] ;
d[i].data = t[i].data ;
cout<<"第"<<i<<"台机器处理的作业号为:"<<S[i][0]<<"; "
<<"所需时间分别为:"<<d[i].data<<endl;
}
}
else{ //B、当作业数n> 机器数m的情况
for(i=0; i<m; i++){ //记录第一次的分配
S[i][0]=p[i] ;
d[i].data = t[i].data ;
cout<<"第"<<i+1<<"台机器处理的作业号为:"<<S[i][0]<<"; "
<<"所需时间为:"<<d[i].data<<endl;
}
for(i=m; i<n; i++){
int j=sortmin(d,m);
cout<<"下一次为机器"<<j+1<<"来处理作业"; //j验证第一次是正确的
S[j][++h[j]]=p[i];
cout<<" ,并且此次机器"<<j+1<<"处理的作业为:"<<S[j][h[j]]+1<<"";
d[j].data += t[i].data;
cout<<endl;
}
}
}
int main()
{
inti,n,m;
cout<<"输入作业个数n和机器个数m:";
cin>>n>>m;
cout<<"输入完成各作业所需要的处理时间:"<<endl;
for(i=0;i<n; i++){
cin>>t[i].data;
t[i].index=i;
}
cout<<endl<<"各机器所处理的作业情况为:"<<endl;
cout<<endl;
duoji(t, n, m);
return0;
}
====================================================
2、活动安排问题
4
1 4
3 5
0 6
5 7
#include<iostream.h>
#include<algorithm>
using namespace std;
struct Data{
int s,f;
}time[100];
bool cmp(Data a, Data b){
return a.f<=b.f;
}
void ActiveManage(Data time[], bool a[ ], intn)
{ //各活动的起始时间和结束时间存储于数组s和f中且
//按结束时间的非减序排列
sort(time+1, time+n+1, cmp);
int i,j,count, rode[100],k=1;
a[1]=1;
j=1;count=1; rode[1]=1;
for(i=2; i<=n; i++) //从 活动i 开始寻找与 活动j 相容的活动,j从1开始,如此循环贪心寻找
{
if (time[i].s >= time[j].f ) {
a[i]=1;
j=i;
rode[++k]=i;
count++;
}
elsea[i]=0;
}
cout<<"共有"<<count<<"个活动,它们分别是:"<<endl;
for(i=1; i<=k;i++)
cout<<"活动:"<<rode[i]<<""<<endl;
}
void main(){
int n,i;
bool a[100];
cin>>n;
for(i=1; i<=n; i++)
cin>>time[i].s>>time[i].f;
ActiveManage(time,a,n);
}
===================================
3、背包问题
3
20 30 10
60 120 50
50
#include<iostream>
#include<algorithm>
using namespace std;
struct Data
{
floatdata;
intindex;
};
Data origData[100];
bool cmp(Data a, Data b){
returna.data>b.data;
}
float Bag(float w[],float v[],float C,intn){
int i,x[100];
float vsum=0;
float r[100], w1[100], v1[100];
for(i=1; i<=n; i++)
r[i]=v[i]/w[i];
for ( i=1; i<=n; i++){ //初始化OrigData[]数组,记录v[i]/w[i]
origData[i].data = r[i];
origData[i].index = i;
}
sort(origData+1,origData+n+1,cmp); //排列OrigData[]数组 又是下标的问题
for(i=1; i<=n; i++){ //根据v[i]/w[i]的降序排列重排列w[]和v[]
w1[i]=w[origData[i].index];
v1[i]=v[origData[i].index];
}
memset(x,0 ,sizeof(x));
i=1;
while(w1[i]<=C){
origData[i].data=1;
C -= w1[i];
vsum +=v1[i];
i++;
}
origData[i].data = C/w1[i];
vsum += v1[i] * origData[i].data; //此处纠结了好久。。。
cout<<"所选物品及百分比为:(1代表全选,0代表不选)"<<endl;
for(int j=1; j<=i; j++)
cout<<origData[j].data<<"";
cout<<endl;
return vsum;
}
void main(){
int n,i,j;
float vsum=0;
floatw[100],v[100],C;
cout<<"输入物品的数量:";
cin>>n;
cout<<"输入这"<<n<<"个物品的重量:"<<endl;
for(i=1;i<=n; i++)
cin>>w[i];
cout<<"输入这"<<n<<"个物品的价值:"<<endl;
for(j=1;j<=n; j++)
cin>>v[j];
cout<<"输入背包容量C:"<<endl;
cin>>C;
floatrs=Bag(w,v,C,n);
cout<<"背包中的物品最大价值容量为:"<<rs<<endl;
}
=============================================
**********************************************
动态规划法
1、最大子段和
#include<iostream.h>
#include<algorithm>
using namespace std;
//数列b[]代表前j个数的最大子段和(是加上a[j]的值)
int DPMaxSum(int a[ ], int n){
int j,b[100];
b[1]=a[1]; //下标为1到n
for(j=2;j<=n; j++){
if(b[j-1]>0) b[j]=b[j-1]+a[j];
else b[j] = a[j];
}
sort(b+1,b+n+1);//注意数组与此处排序函数的一致性
-------------------------(还有一个递推式)
return b[n];
}
void main(){
int a[100];
int i,n;
cout<<"请输入整数个数:";
cin>>n;
cout<<"请输入这"<<n<<"个整数所组成的序列:";
for(i=1;i<=n; i++)
cin>> a[i];
int rs=DPMaxSum(a, n);
cout<<"该序列的最大字段和为:"<<rs<<endl;
}
=================================================
2、近似串匹配
5 14 1
happy
Have a hsppy day!
//-----唯一的问题是不识别空格符
#include<iostream.h>
int min(int a,int b,int c){
int min=a;
if(a>=b) min =b;
if(min >=c) min=c;
return min;
}
//P[m]数组存放输入的样本,T[n]数组存放匹配的文本, K-近似匹配
//D[i][j]数组存放样本P前缀p1到pi与文本T前缀T1到Tj的最小差别数
int ASM(char P[ ], char T[ ], int m, int n,int K){
int j,i, D[100][100];
for (j=1;j<=n; j++) //初始化第0行
D[0][j]=0;
for (i=0;i<=m; i++) //初始化第0列
D[i][0]=i;
for (j=1;j<=n; j++) //根据递推式依次计算每一列
{
for (i=1; i<=m; i++)
{
if (P[i]==T[j] )
D[i][j]= min( D[i-1][j-1],D[i-1][j]+1, D[i][j-1]+1);
else
D[i][j]=min( D[i-1][j-1]+1,D[i-1][j]+1, D[i][j-1]+1);
}
if ( D[m][j]<=K) return j;//输出匹配末位置
}
}
void main(){
char P[100], T[100];
int i,m,n,K;
cout<<"请输入样本字符数m,文本字符数n和 K值:"<<endl;
cin>>m>>n>>K;
cout<<"请输入样本字符串和文本字符串:"<<endl;
for(i=1;i<=m; i++)
cin>>P[i];
for(i=1;i<=n; i++)
cin>>T[i];
cout<<"最大匹配数是:"<<ASM(P,T,m,n,K)<<endl;
}
====================================================
3、最优二叉树
请输入字符个数n:
4
请输入字符的查找概率
0.1 0.2 0.4 0.3
最优二叉查找树的平均比较次数是:1.7
Press any key to continue
#include<iostream.h>
#define MAX 999
//数组p[]存放n个字符的查找概率
//数组C[i][j]是二叉查找树T(i,j)的平均比较次数
//数组R[i][j]是二叉查找树T(i,j)的根节点序号
double OptimalBST( int n, double p[100 ],double C[100 ][100 ], int R[ 100][100 ] ){
int i,j,d;
for (i=1; i<=n; i++) { //初始化
C[i][i-1]=0;
C[i][i]=p[i];
R[i][i]=i;
}
C[n+1][n]=0;
for (d=1;d<n; d++) //按对角线逐条计算
for(i=1; i<=n-d; i++){
j=i+d;
double min, sum;
int mink;
min=MAX; mink=i; sum=0;
for (int k=i;k<=j; k++){
sum=sum+p[k];
if(C[i][k-1]+C[k+1][j]<min) {
min=C[i][k-1]+C[k+1][j];
mink=k;
}
}
C[i][j]=min+sum;
R[i][j]=mink;
}
returnC[1][n];
}
void main(){
int i, R[100][100] ,n ;
doubleP[100],C[100][100];
cout<<"请输入字符个数n:"<<endl;
cin>>n;
cout<<"请输入字符的查找概率"<<endl;
for(i=1;i<=n; i++)
cin>>P[i];
cout<<"最优二叉查找树的平均比较次数是:"<<OptimalBST(n,P, C ,R)<<endl;
}
=========================================
4、最长公共子序列
输入两个序列的个数m,n:
6 9
a b c b d b
a c b b a b d b b
最长公共子序列是:a c b d b
最长公共子序列的长度是:5
Press any key to continue
#include<iostream.h>
//L[i][j]为序列x[i]与y[j]序列的最长公共子序列的长度
//S[][]记录三种状态,回溯最长公共子序列
int CommonOrder(int m, int n, char x[ ], chary[ ], char z[]){
int L[100][100],i,j,k,S[100][100];
for (j=0; j<=n; j++) //初始化第0行
L[0][j]=0;
for (i=0; j<=m; i++) //初始化第0列
L[i][0]=0;
for (i=1; i<=m; i++)
for (j=1;j<=n; j++)
if (x[i]==y[j]) {
L[i][j]= L[i-1][j-1]+1;
S[i][j] = 1;
}
else if(L[i][j-1] >= L[i-1][j]) {
L[i][j] =L[i][j-1];
S[i][j]=2;
}
else {
L[i][j]=L[i-1][j];
S[i][j]=3;
}
cout<<"最长公共子序列是:";
i=m; j=n; k=L[m][n];
while (i>0&& j>0) {
if (S[i][j]==1){
z[k]=x[i];
k--; i--; j--;
}
else if (S[i][j]==2) j--;
elsei--;
}
for(i=1;i<=L[m][n]; i++)
cout<<z[i]<<"";
cout<<endl;
returnL[m][n];
}
void main(){
charx[100],y[100],z[100];
int n,m;
cout<<"输入两个序列的个数m,n:"<<endl;
cin>>m>>n;
for(int i=1; i<=m; i++)
cin>>x[i];
for(i=1; i<=n; i++)
cin>>y[i];
cout<<"最长公共子序列的长度是:"<<CommonOrder(m,n,x,y,z)<<endl;
}
======================================
5、0-1背包问题
输入物品数量:
3
输入这3个物品的重量:
20 30 10
输入这3个物品的价值:
60 120 50
输入背包容量C:
50
输出装入背包的物品:1表示装入,0表示未装入
1 1 0
背包中的物品最大价值容量为:180
Press any key to continue
#include<iostream.h>
int max(int a,int b){
return a>b ? a : b;
}
//V[i][j]表示在前i个物品中能够装入容量为j的背包中的物品的价值最大值
//V[i][0] , V[0][j]都为0;
int KnapSack(int n, int w[ ], int v[ ],int C){ //n个物品,C为最大容量
inti,j;
intV[100][100],x[100];
for(i=0; i<=n; i++) //初始化第0列
V[i][0]=0;
for(j=0; j<=C; j++) //初始化第0行
V[0][j]=0;
for(i=1; i<=n; i++) //计算第i行,进行第i次迭代
for (j=1; j<=C; j++)
if(j<w[i]) //第i个物品不能装入(超重)
V[i][j]=V[i-1][j];
else //满足装入条件(装入后未超重),但也可不装
V[i][j]=max(V[i-1][j], V[i-1][j-w[i]]+v[i]); //装或者不装后的价值的最大值
//求装入背包的物品:1表示装入,0表示未装入
j=C;
for(i=n; i>0; i--){
if(V[i][j]>V[i-1][j]) {
x[i]=1;
j=j-w[i];
}
else x[i]=0;
}
//输出装入背包的物品:1表示装入,0表示未装入
cout<<"输出装入背包的物品:1表示装入,0表示未装入"<<endl;
for(i=1; i<=n; i++)
cout<<x[i]<<"";
cout<<endl;
return V[n][C]; //返回背包取得的最大价值
}
int main(){
intn,i,j,w[100],v[100],C;
cout<<"输入物品数量:"<<endl;
cin>>n;
cout<<"输入这"<<n<<"个物品的重量:"<<endl;
for(i=1;i<=n; i++)
cin>>w[i];
cout<<"输入这"<<n<<"个物品的价值:"<<endl;
for(j=1;j<=n; j++)
cin>>v[j];
cout<<"输入背包容量C:"<<endl;
cin>>C;
cout<<"背包中的物品最大价值容量为:"<<KnapSack(n, w, v,C)<<endl;
return0;
}
========================================
6、多段图最短路径
输入城市个数:10
输入城市之间的距离:
100 4 2 3 100 100 100 100 100 100
100 100 100 100 9 8 100 100 100 100
100 100 100 100 6 7 8 100 100 100
100 100 100 100 100 4 7 100 100 100
100 100 100 100 100 100 100 5 6 100
100 100 100 100 100 100 100 8 6 100
100 100 100 100 100 100 100 6 5 100
100 100 100 100 100 100 100 100 100 7
100 100 100 100 100 100 100 100 100 3
100 100 100 100 100 100 100 100 100 100
最短路径长为:16
最短路径为:0->3->5->8->9
Press any key to continue
#include<iostream.h>
//cost[i]表示从顶点i到顶点n-1 的最短路径
//path[i]表示从顶点i到顶点n-1的最短路径上的下一顶点
void duoduantu(int cost[100],intc[100][100],int path[100],int k,int n){
int i,j;
for(i=0; i<n; i++)
cost[i]=c[i][n-1]; //初始,c[][]记录各顶点间的距离
for(i=n-2; i>=k; i--)
for(j=i+1; j<n; j++)
if( (cost[j] + c[i][j]) <cost[i]){
cost[i]= cost[j] + c[i][j] ;
path[i]=j;
}
}
int main(){
int i,j,n;
int c[100][100],cost[100], path[100];
cout<<"输入城市个数:";
cin>>n;
cout<<"输入城市之间的距离:";
for(i=0;i<n; i++)
for(j=0;j<n; j++)
cin>>c[i][j];
duoduantu(cost,c,path,0,n);
cout<<"最短路径长为:"<<cost[0]<<endl;
for(i=0; i<=n-2; i++)
duoduantu(cost,c,path,i,n);
cout<<"最短路径为:"<<0<<"->";
i=0;
do{
cout<<path[i];
if(i!=n-2)cout<<"->";
i=path[i];
}while(i<n-2);
cout<<n-1<<endl;
return 0;
}
=========================================