目录
01背包问题
描述:
有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。
第 i 件物品的体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。
输入:
第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。
输出:
输出一个整数,表示最大价值。
输入样例
4 5 1 2 2 4 3 4 4 5
输入样例
8
源代码
#include <iostream>
#include <algorithm>
using namespace std;
#define Max 101
int N,V;
int val[Max][Max];//val[i][j]表示物品1,2,~,i,背包最大容量为j时的最大价值量
struct things{
int v[Max];
int w[Max];
}thing;
void Knapsack(int N,int V,int *w,int *v){
for(int i = 0; i <= N; i++){
val[i][0] = 0;
}
for(int j = 0; j <= V; j++){
val[0][j] = 0;
}
for(int i = 1; i <= N; i++){
for(int j = 1; j <= V; j++){
if(w[i] > j){
val[i][j] = val[i-1][j];
}
else{
val[i][j] = max(val[i-1][j],val[i-1][j-w[i]]+v[i]);
}
}
}
}
int main()
{
cin >> N >> V;
for(int i = 1; i <= N; i++){
cin >> thing.w[i] >> thing.v[i];
}
Knapsack(N,V,thing.w,thing.v);
cout << val[N][V];
}
快速排序
描述
利用快速排序算法将读入的 NN 个数从小到大排序后输出。
快速排序是信息学竞赛的必备算法之一。对于快速排序不是很了解的同学可以自行上网查询相关资料,掌握后独立完成。
输入
第 1 行为一个正整数 N,第 2 行包含 N 个空格隔开的正整数 a_i ,为你需要进行排序的数,数据保证了 A_i 不超过 10^9 。
输出
将给定的 N 个数从小到大输出,数之间空格隔开,行末换行且无空格。
输入样例 1
5 4 2 4 5 1
输出样例 1
1 2 4 4 5
源代码
#include <iostream>
#include <algorithm>
using namespace std;
void QuickSort(int *a,int first,int last){
if(first >= last){
return;
}
int i = first,j = last;
int k = a[first];
while(i != j){
while(k <= a[j] && i < j){
j--;
}
swap(a[i],a[j]);
while(k > a[i] && i < j){
i++;
}
swap(a[i],a[j]);
}
QuickSort(a,first,i);
QuickSort(a,i+1,last);
}
int main()
{
int n;
cin>> n;
int a[n];
for(int i = 0;i < n;i++){
cin >> a[i];
}
QuickSort(a,0,n-1);
for(int i = 0; i < n; i++){
cout << a[i] << " ";
}
cout << endl;
}
最长公共子序列问题
描述
给定两个长度分别为 N 和 M 的字符串 A 和 B,求既是 A 的子序列又是 B 的子序列的字符串长度最长是多少。
输入
第一行包含两个整数 N 和 M。
第二行包含一个长度为 N 的字符串,表示字符串 A。
第三行包含一个长度为 M 的字符串,表示字符串 B。
字符串均由小写字母构成。
输出
输出一个整数,表示最大长度。
输入样例 1
4 5 acbd abedc
输出样例 1
3
提示
1≤N,M≤1000
源代码
#include <iostream>;
#include <cstring>;
#include <algorithm>;
#define Max 101
using namespace std;
int n,N,M;
char A[Max],B[Max];
int val[Max][Max];
void Mlen(char *A,char *B){
for(int i = 0; i <= N; i ++){
val[i][0] = 0;
}
for(int j = 0; j <= M; j++){
val[0][j] = 0;
}
for(int i = 1; i <= N; i++){
for(int j = 1; j <= M; j++){
if(A[i] == B[j]){
val[i][j] = val[i-1][j-1] + 1;
}else{
val[i][j] = max(val[i-1][j],val[i][j-1]);
}
}
}
}
int main()
{
cin >> N >> M;
for(int i = 1; i <= N; i++){
cin >> A[i];
}
for(int j = 1; j <= M; j++){
cin >> B[j];
}
Mlen(A,B);
cout << val[N][M] << endl;
}
排列数字
描述
给定一个整数 n,将数字 1∼n 排成一排,将会有很多种排列方法。
现在,请你按照字典序将所有的排列方法输出。
输入
共一行,包含一个整数 n。
输出
按字典序输出所有排列方案,每个方案占一行。
输入样例 1
3
输出样例 1
1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1
提示
1≤n≤7
源代码
#include<iostream>
using namespace std;
int a[10];
bool vis[10]={0};
void dfs(int x, const int& m)//x计数以搜索的数的个数
{
if(x>m)//搜索数目足够是输出所有的数
{
for(int i=1;i<= m;i++)
cout<<a[i]<<' ';
cout<<endl;
return;
}
for(int i=1;i<=m;i++)
if(!vis[i])//判断数i是否已经被载入数组
{
a[x]=i;//置 排列的第一个数 a[1] = 1;
vis[i]=1;//表示该值加入到数组以提供输出
dfs(x+1,m);// 递归该函数给a[2]赋值;如果x加到大于m,代表a的所有值赋完,就直接输出
vis[i]=0;//每次输出之后重置
}
}
int main()
{
int n;
cin>>n;
dfs(1,n);
return 0;
}
电视节目问题
源代码
//电视节目问题
#include <iostream>
#include <algorithm>
using namespace std;
struct Ti{
int ti_s;
int ti_e;
}ti[101];
int main()
{
int n;
cin >> n;
for(int i = 1; i <= n; i++){
cin >> ti[i].ti_s >> ti[i].ti_e;
}
//想看最多的节目,就应该找先结束的节目来看
for(int i = 1; i <= n; i++){
for(int j = i+1; j <= n; j++){
if(ti[i].ti_e > ti[j].ti_e){
swap(ti[i].ti_e,ti[j].ti_e);
swap(ti[i].ti_s,ti[j].ti_s);
}
}
}
cout << endl;
for(int i = 1; i <= n;i++){
cout << ti[i].ti_s << " " << ti[i].ti_e << endl;
}
int res = 1;
int cmp = ti[1].ti_e;
for(int i = 2; i <= n; i++){
if(ti[i].ti_s >= cmp)
res ++;
cmp = ti[i].ti_e;
}
cout << res << endl;
}
归并排序
源代码
#include <iostream>
using namespace std;
int tempArr[101];
//打印函数
void print_arr(int arr[], int n){
for(int i = 0; i < n; i++){
cout << arr[i] << " ";
}
cout << endl;
}
//合并
void merge(int arr[], int left, int mid, int right){
//标记左右半区的第一个元素
int l_pos = left;
int r_pos = mid + 1;
//临时数组元素的下标
int pos = left;
//合并
//左右半区都有元素
while(l_pos <= mid && r_pos <= right){
if(arr[l_pos] < arr[r_pos]){
tempArr[pos++] = arr[l_pos++];
}
else{
tempArr[pos++] = arr[r_pos++];
}
}
//合并左右半区剩余元素
while(l_pos <= mid){
tempArr[pos++] = arr[l_pos++];
}
while(r_pos <= right){
tempArr[pos++] = arr[r_pos++];
}
//把临时数组中合并后的元素复制回来原来的数组
while(left <= right){
arr[left] = tempArr[left];
left ++;
}
}
//归并排序
void msort(int arr[],int left, int right){
if(left < right){
int mid = (left + right)/2;
//递归划分左右半区
msort(arr,left,mid);
msort(arr,mid + 1,right);
//合并已经排序的部分
merge(arr,left,mid,right);
}
}
int main()
{
int arr[] = {9,5,2,7,12,4,3,1,11};
int n = 9;
print_arr(arr,n);
msort(arr,0,n-1);
print_arr(arr,n);
return 0;
}
杨辉三角
源代码
#include <iostream>
using namespace std;
int main()
{
int n;
int a[25][25] = {1};//设定a[0][0]=1很关键
cin >> n;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
a[i][j] = a[i-1][j] + a[i-1][j-1];
}
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(a[i][j] != 0){
if(i == j){
cout << a[i][j];
}
else{
cout << a[i][j] << " ";
}
}
}
cout << endl;
}
}
二分查找
源代码
#include <iostream>
using namespace std;
int search(int *a,int size,int target){
int first = 0;
int last = size - 1;//左边右边全部取闭区间
while(first <= last){
int mid = (first + last)/2;
if(a[mid] == target){
return target;
}
else if(a[mid] > target){
last = mid - 1;
}
else{
first = mid + 1;
}
}
return -1;
}
int main()
{
int n;
cin >> n;
int a[n];
for(int i = 0; i < n; i++)
cin >> a[i];
int target;
cin >> target;
cout << search(a,n-1,target) << endl;
}