基础算法之贪心法1
来源:互联网 发布:移动数据采集器 编辑:程序博客网 时间:2024/05/14 17:17
1.2贪心法(1)
声明:本分类中的所有博文(包括此篇博文),均为本人在学习《实用算法分析与程序设计》时所作的笔记。其中的例子全引用自《实用算法分析与程序设计》。C++代码为个人原创,转载请注明出处。
在某些情况下局部最优选择能得出全局最优解。如下。
例1.删数问题
int main(){char data[256];cout<<"please input the number"<<endl;cin>>data;int n;cout<<"please input the number of char you want to delete."<<endl;cin>>n; //输入删除的数字数int i,j,p,q; //循环变量 int max; //记录每次删除的数字的下标for(i=1;i<=n;i++){max=0;for(j=1;j<strlen(data);j++) //从高到底寻找递减区间,如果没有则是最后一个{if(data[j]>=data[max])max=j;else break;}if(max==0){for(p=1;p<strlen(data);p++) if(data[p]!='0')break;for(q=p;q<strlen(data);q++){data[q-p]=data[q];}data[q-p]='\0';}else{for(q=max+1;q<strlen(data);q++){data[q-1]=data[q];}data[q-1]='\0';}}cout<<data<<endl;return 0;}
例2.背包问题
0-1背包
比如有5个物品 重量分别为weight[6] {2,4,3,1,5} (weight[0]不使用)
价值分别为value[6] {4,6,2,2,9} (value[0]不使用)
要求总重量不超过12。
我们先建立一个数组,array[6][12]
array[m][n]表示标号为m及标号大于m的物品允许放入背包中,如果重量不超过n,那么最好的状况总价值是多少。
如array[3][7]表示3号4号5号允许放入背包中,重量不超过8时,最好状况总价值死多少。观察得最好是把4号和5号放进去,总重量6(小于7),总价值应该是11。所以array[3][7]=11;
有个规律,array[m][n]=max{array[m+1][n], array[m+1][n-weight[m]] +value[m]}即考虑m号物品要不要放进去,不放进去的状况总价值=array[m+1][n],放进去总价值=array[m+1][n-weight[m]] +value[m]。
#include <iostream>#include <stdio.h>#include<math.h>#include <string.h>#include "stdlib.h"using namespace std;typedef struct{ int object; int weight; int value;}KnapSack;KnapSack * knapSack;int num;int container;int **array=NULL;void Create_KnapSack() //建立物品{ char c; cout<<"input the number of objects"<<endl; cin>>num; knapSack=new KnapSack[num+1]; cout<<"input weight and value of "<<num<<" objects,like 1:4 10"<<endl; for(int i=1;i<=num;i++) { cin>>knapSack[i].object>>c>>knapSack[i].weight>>knapSack[i].value; } cout<<"input the volume of the knapsack:"<<endl; cin>>container;}void Resolve_KnapSack() //解决背包问题{ array=(int **)malloc((num+1)*sizeof(int *));//要加#include “stdlib.h”;不然会提示malloc在此作用域中尚未声明 for(int i=0;i<=num;i++) { array[i]=(int *)malloc((container+1)*sizeof(int)); } for(int j=0;j<=container;j++) { array[num][j]=(j>=knapSack[num].weight)?knapSack[num].value:0; } for(int m=num-1;m>0;m--) { for(int n=0;n<=container;n++) { if(n>=knapSack[m].weight&&array[m+1][n]<=array[m+1][n-knapSack[m].weight]+knapSack[m].value) array[m][n]=array[m+1][n-knapSack[m].weight]+knapSack[m].value; else array[m][n]=array[m+1][n]; } }}bool * Trace_back() //回溯,找哪些物品被放进背包中了{ int c=container; bool *used; used=(bool *)malloc((num+1)*sizeof(bool)); for(int i=1;i<num;i++) { if(array[i][c]==array[i+1][c]) used[i]=0; else { used[i]=1; c-=knapSack[i].weight; } } used[num]=(c==knapSack[num].weight)?1:0; return used;}void Print_KnapSack(bool *used) //打印背包中的物品{ cout<<"the objects used as follows:"<<endl; for(int i=1;i<=num;i++) { if(used[i]) cout<<knapSack[i].object<<": "<<knapSack[i].weight<<" "<<knapSack[i].value<<endl; }}int main(){ bool * used; Create_KnapSack(); Resolve_KnapSack(); used=Trace_back(); Print_KnapSack(used);return 0;}
完全背包问题
基本思路
完全背包问题非常类似于01背包问题,所不同的是每种物品有无限件。也就是从每种物品的角度考虑,与它相关的策略已并非取或不取两种,而是有取0件、取1件、取2件……等很多种。如果仍然按照解01背包时的思路,令f[i][v]表示前i种物品恰放入一个容量为v的背包的最大权值。仍然可以按照每种物品不同的策略写出状态转移方程,像这样:
array[m][n]=max{array[m+1][n], array[m+1][n-k*weight[m]] +k*value[m]} (0<=k*weight[m]<=n )
对其可以进行优化,把它变为一维的。
for i: container...1
array[n]=max{array[n],array[n-weight[i]]+value[i]}
就是相当于把0-1背包化成一维的,每次都覆盖前面那次的结果。#include <iostream>#include <stdio.h>#include<math.h>#include <string.h>#include "stdlib.h"using namespace std;typedef struct{ int object; int weight; int value;}KnapSack;KnapSack * knapSack;int num;int container;int *array=NULL;void Create_KnapSack() //建立物品{ char c; cout<<"input the number of objects"<<endl; cin>>num; knapSack=new KnapSack[num+1]; cout<<"input weight and value of "<<num<<" objects,like 1:4 10"<<endl; for(int i=1;i<=num;i++) { cin>>knapSack[i].object>>c>>knapSack[i].weight>>knapSack[i].value; } cout<<"input the volume of the knapsack:"<<endl; cin>>container;}void Resolve_KnapSack() //解决背包问题{ array=(int *)malloc((container+1)*sizeof(int)); for(int i=0;i<=container;i++) { if(i<knapSack[num].weight)array[i]=0; else array[i]=(i/knapSack[num].weight)*knapSack[num].value; } for(int i=1;i<=container;i++)cout<<" "<<array[i]; cout<<endl; for(int i=num-1;i>=1;i--) { for(int j=1;j<=container;j++) { if(j>=knapSack[i].weight) { int t=array[j-knapSack[i].weight]+knapSack[i].value; array[j]=(t>=array[j])?t:array[j]; } } for(int i=1;i<=container;i++)cout<<" "<<array[i]; cout<<endl; }}void Trace_back(int *used) //回溯,找哪些物品被放进背包中了{ int c=container; memset(used,0,(num+1)*sizeof(int)); for(int i=num;i>=1;i--) { for(int j=i;j>=1;j--) { if(array[c]==(array[c-knapSack[j].weight]+knapSack[j].value)) { used[j]++; c=c-j; break; } } } return ;}int main(){ freopen("input.txt","r",stdin); int * used; used=(int *)malloc((num+1)*sizeof(int)); Create_KnapSack(); Resolve_KnapSack(); cout<<"The max value is: "<<array[container]<<endl; Trace_back(used); cout<<"name: "; for(int i=1;i<=num;i++)cout<<" "<<i; cout<<endl; cout<<"numbers:"; for(int i=1;i<=num;i++)cout<<" "<<used[i]; fclose(stdin);return 0;}
部分背包问题
问题描述:n件物品,第i件物品价值 vi 元,重wi 磅。希望用 W磅的背包 拿走最重的物品。第i件物品可以都拿走,也可以拿走一部分。(物品可以分割所以称为部分背包)
按照物品价值重量比,每次选择价值重量比最高的物体放入,可保证放入的价值一定最大。
#include <iostream>#include <stdio.h>#include<math.h>#include <string.h>#include "stdlib.h"using namespace std;typedef struct{ int object; int weight; int value;}KnapSack;KnapSack * knapSack;int num;int container;int *array=NULL;void Create_KnapSack() //建立物品{ char c; cout<<"input the number of objects"<<endl; cin>>num; knapSack=new KnapSack[num+1]; cout<<"input weight and value of "<<num<<" objects,like 1:4 10"<<endl; for(int i=1;i<=num;i++) { cin>>knapSack[i].object>>c>>knapSack[i].weight>>knapSack[i].value; } cout<<"input the volume of the knapsack:"<<endl; cin>>container;}void Sort_KnapSack(){ int i,j; float a1,a2; int temp; for(i=1;i<=num;i++) { for(j=1;j<=num-i;j++) { a1=((float)knapSack[j].value)/((float)knapSack[j].weight); a2=((float)knapSack[j+1].value)/((float)knapSack[j+1].weight); if(a2>a1) { temp=knapSack[j].value; knapSack[j].value=knapSack[j+1].value; knapSack[j+1].value=temp; temp=knapSack[j].weight; knapSack[j].weight=knapSack[j+1].weight; knapSack[j+1].weight=temp; temp=knapSack[j].object; knapSack[j].object=knapSack[j+1].object; knapSack[j+1].object=temp; } } }}float Resolve_KnapSack(int *used) //解决背包问题{ int left=container; float value=0; for(int i=1;i<=num;i++) { if(knapSack[i].weight<left) { used[knapSack[i].object]=knapSack[i].weight; left-=knapSack[i].weight; value+=knapSack[i].value; if(left==0)break; }else { used[knapSack[i].object]=left; left=0; value+=((float)knapSack[i].value)/((float)knapSack[i].weight)*((float)left); break; } } return value;}int main(){ Create_KnapSack(); Sort_KnapSack(); int *used=new int[num+1]; float maxValue; maxValue=Resolve_KnapSack(used); int i; cout<<maxValue<<endl; for(i=1;i<=num;i++) { cout<<i<<": "<<used[i]<<endl; }return 0;}
- 基础算法之贪心法1
- 基础算法之贪心算法
- 基础入门之贪心算法
- 贪心算法--1基础
- 贪心算法基础之完美字符串 51nod 贪心总结
- 贪心算法基础之独木舟问题 51nod 贪心教程
- 【算法基础】----贪心算法
- 贪心算法1之1016
- 【算法基础】----贪心算法的应用之Huffman编码
- 贪心算法基础
- 算法----五大算法之贪心法
- 算法----五大算法之贪心法
- 算法之贪心算法
- 算法之贪心算法
- 【贪心算法(一)】贪心算法基础
- 算法基础(5) 贪心算法
- 数据结构基础 之 最短路径 贪心算法
- 贪心算法基础之活动时间安排(一)安排 51nod 贪心教程
- c# console控制台类的一些用法
- Nagios
- 关于Mysql中UDF函数的思考(一)
- .net 多态!
- Android ViewPager多页面滑动切换以及动画效果
- 基础算法之贪心法1
- [机器学习] PCA理论
- ASP利用IP138获IP地理位置
- top命令学习笔记
- session的属性设置
- Factorials
- poj 3286 How many 0's? (数位DP+ 统计)
- Bootstrap+Timeliner+Github+JQUERY创建程序员的简历(二)---专业技能表
- 系统时间同步到互联网时间