CSP普及赛程序模板
1.数学-质数
https://www.luogu.com.cn/problem/P1217
#include<bits/stdc++.h> using namespace std; bool isPalindromes(int n){//判断回文数 int a[20]; int m=1; while(n>0){//数字分离 a[m]=n%10; n=n/10; m++; } for(int i=1;i<=m/2;i++){//判断左右两边是否相同 if(a[i]!=a[m-i]){ return 0;//不同的话返回0 } } return 1;//否则返回1 } bool isPrimes(int n){ if(n==2){ return 1; } for(int i=2;i<=sqrt(n);i++){//判断质数 if(n%i==0){ return 0; } } return 1; } int main(){ int n,m; cin>>n>>m; if(n==2){//2的话要特殊判断 cout<<"2"<<endl; } if(n%2==0){//偶数的话就加1 n++; } for(int i=n;i<=m;i=i+2){//跳过偶数 if(isPalindromes(i)==0){ continue; } if(isPrimes(i)==0){ continue; } cout<<i<<endl; } }
质数线性筛法-埃氏筛法-欧拉筛法
https://www.cnblogs.com/myeln/articles/15112594.html
2.二分、贪心 -分割木材、切割绳子
有 n 条绳子,每条绳子的长度已知且均为正整数。
绳子可以以任意正整数长度切割,但不可以连接。现在要从这些绳子中切割出 m 条长度相同的绳段,求绳段的最大长度是多少
输入:第一行是一个不超过 100 的正整数 n,第二行是 n 个不超过106的正整数,表示每条绳子的长度,第三行是一个不超过108的正整数 m。
输出:绳段的最大长度,若无法切割,输出 Failed
#include<iostream> using namespace std; int n, m, i, lbound, ubound, mid, count; int len[100]; // 绳子长度 int main(){ cin >> n; count = 0; for (i = 0; i < n; i++){ cin >> len[i]; count=count+len[i]; } cin >> m; if (count<m){ cout << "Failed" << endl; return 0; } lbound = 1; ubound = 1000000; while (lbound<ubound){ mid = lbound+ubound+1)/2; count = 0; for (i = 0; i < n; i++) count=count+len[i]/mid; if (count < m) ubound = mid - 1; else lbound = mid; } cout << lbound << endl; return 0; }
3.二分-中位数
给定 n(n 为奇数且小于 1000)个整数,整数的范围在 0~m(0<m<2^31)之间,请使用二分法求这 n 个整数的中位数。
所谓中位数,是指将这 n 个数排序之后,排在正中间的数
#include <iostream> using namespace std; const int MAXN = 1000; int n, i, lbound, rbound, mid, m, count; int x[MAXN]; int main(){ cin >> n >> m; for (i = 0; i < n; i++) cin >> x[i]; lbound = 0; rbound = m; while (lbound < rbound){ mid = (lbound + rbound) / 2; count = 0; for (i = 0; i < n; i++) if (x[i] > mid) count++; if (count > n / 2) lbound = mid + 1; else rbound = mid; } cout << rbound << endl; return 0; } // 5 100 // 1 3 5 7 9
P1168 中位数
https://www.luogu.com.cn/problem/P1168
4.前缀和 -平衡点
http://iai.sh.cn/problem/442
#include<bits/stdc++.h> using namespace std; int a[100005],b[100005],c[100005]; int main(){ int n; long long ans,l=0,r=0; cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; } for(int i=1;i<=n;i++){ b[i]=b[i-1]+a[i]; } for(int i=n;i>=1;i--){ c[i]=c[i+1]+a[i]; } for(int i=2;i<=n;i++){ r=r+(i-1)*a[i]; } ans=r; for(int i=1;i<=n;i++){ l=l+b[i]; r=r-c[i+1]; ans=min(ans,abs(l-r)); } cout<<ans; }
5.前缀和、贪心 -最大子矩阵
http://noi.openjudge.cn/ch0406/1768/
#include<iostream> #include<algorithm> using namespace std; int a[110][110]; int main() { int n; cin >> n; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) { cin >> a[i][j]; a[i][j] += a[i - 1][j]; //求出每一列的前缀和 } int Max = -1e9; for(int i = 1; i <= n; i++){ for(int j = i; j <= n; j++){ int now = 0; for(int k = 1; k <= n; k++){ now = max(now, 0) + a[j][k] - a[i - 1][k]; //如果now小于0了,如果加上的话数值会变小,所以干脆就不用加了 Max = max(Max, now); } } } cout << Max << endl; return 0; }
6.递归 - 全排列
https://www.luogu.com.cn/problem/P1706
#include<bits/stdc++.h> using namespace std; //定义变量 n,当前排列记录数组,当前排列数字是否使用数组 int n,used[10],curRow[10]; void dfs(int k){ //满足退出条件 输出当前排列数组 if(k==n){ for(int i=1;i<=n;i++){ cout<<setw(5)<<curRow[i]; } cout<<endl; return; } // 1~n全部展开 for(int i=1;i<=n;i++){ //判断当前数字未使用进入 //当前数组是否使用,在定义数组是否设置 if(used[i]==0){ //设置 used[i]=1; // 记录到当次排列数组 curRow[k+1]=i; //递归dfs dfs(k+1); //恢复 used[i]=0; } } } int main(){ //输入 cin>>n; //调用dfs 0开始 深度优先搜索 dfs(0); return 0; }
7.高精度加法
https://www.luogu.com.cn/problem/P1601
#include <bits/stdc++.h> using namespace std; const int MAXN = 506; int a[MAXN], b[MAXN], sum[MAXN]; char ac[MAXN], bc[MAXN]; //int lena, lenb, lensum; // 使用a[0] b[0] sum[0] 表示长度 void convert(char ca[], int a[]){ int len = strlen(ca); for(int i = 1; i <= len; i++){ a[i] = ca[len - i] - '0'; } a[0] = len; } void print(int ans[]){ for(int i = ans[0]; i >= 1; i--) printf("%d", ans[i]); } int add(int a[], int b[], int sum[]){ int i = 1, x = 0; while(i <= a[0] || i <= b[0]) { sum[i] = a[i] + b[i] + x; x = sum[i]/10; sum[i] = sum[i] % 10; i++; } while(x) { sum[i] = x % 10; x /= 10; i++; } sum[0] = i - 1; } int main(){ scanf("%s", ac); scanf("%s", bc); convert(ac, a); convert(bc, b); add(a, b, sum); print(sum); return 0; }
8.高精度减法
https://www.luogu.com.cn/problem/P2142
#include <bits/stdc++.h> using namespace std; const int MAXN = 10088; char ac[MAXN], bc[MAXN]; int a[MAXN], b[MAXN], ans[MAXN]; // 使用a[0] b[0] ans[0] 表示长度 void convert(char ca[], int a[]){ int len = strlen(ca); for(int i = 1; i <= len; i++){ a[i] = ca[len - i] - '0'; } a[0] = len; } void print(int ans[]){ for(int i = ans[0]; i >=1; i--) printf("%d", ans[i]); } int compare(int a[], int b[]){ int lena = a[0]; int lenb = b[0]; if(lena > lenb) return 1; if(lenb > lena) return -1; for(int i = lena; i >=1; i--){ if(a[i] > b[i]) return 1; if(a[i] < b[i]) return -1; } return 0; //a==b } int sub(int a[], int b[], int ans[]){ int i; int *big, *little; if(compare(a, b) >= 0) { big = a; little = b; } else { big = b; little = a; } for(i = 1; i <= big[0]; i++) { ans[i] = big[i] - little[i] + ans[i]; if(ans[i] < 0) { ans[i] += 10; ans[i + 1] -= 1; } } i = big[0]; while(ans[i] == 0 && i > 1) i--; if(big == b) ans[i] *= -1; ans[0] = i; } int main(){ scanf("%s", ac); scanf("%s", bc); convert(ac, a); convert(bc, b); sub(a, b, ans); print(ans); return 0; }
9.高精度乘法
https://www.luogu.com.cn/problem/P1303
#include <bits/stdc++.h> using namespace std; char ac[2008], bc[2008]; int a[2008], b[2008], ans[4000008]; // 使用a[0] b[0] ans[0] 表示长度 void convert(char ca[], int a[]){ int len = strlen(ca); for(int i = 1; i <= len; i++){ a[i] = ca[len - i] - '0'; } a[0] = len; } void print(int ans[]){ for(int i = ans[0]; i >=1; i--) printf("%d", ans[i]); } void mult(int a[], int b[], int ans[]){ int i, j, len; for(i = 1; i <= a[0]; i++){ for(j = 1; j <= b[0]; j++) { ans[i+j-1] += a[i] * b[j]; } } len = a[0] + b[0]; for(i = 1; i < len; i++) { ans[i + 1] += ans[i] / 10; ans[i] %= 10; } while(ans[i] == 0 && i > 1) i--; ans[0] = i; } int main(){ scanf("%s", ac); scanf("%s", bc); convert(ac, a); convert(bc, b); mult(a, b, ans); print(ans); return 0; }
10.高精度除法
https://www.luogu.com.cn/problem/P1480 --有问题
#include <bits/stdc++.h> using namespace std; const int MAXN = 5008; char ac[MAXN]; int a[MAXN], b, ans[MAXN]; // 使用a[0] b[0] ans[0] 表示长度 void convert(char ca[], int a[]){ int len = strlen(ca); for(int i = 1; i <= len; i++){ a[i] = ca[len - i] - '0'; } a[0] = len; } void print(int ans[]){ for(int i = ans[0]; i >=1; i--) printf("%d", ans[i]); } void div(int a[], int b, int ans[]){ int i, x = 0; for(i = a[0]; i >= 1; i--) { x = x * 10 + a[i]; ans[i] = x / b; x = x % b; } i = a[0]; while(ans[i] == 0 && i > 1) i--; ans[0] = i; } int main(){ scanf("%s", ac); scanf("%d", &b); convert(ac, a); div(a, b, ans); print(ans); return 0; }
11.进制转换 任意进制
https://www.luogu.com.cn/problem/P1143
#include <bits/stdc++.h> using namespace std; int a[66]; char str[66]; char c[16] = {'0', '1', '2', '3', '4','5', '6', '7', '8', '9', 'A','B', 'C', 'D', 'E', 'F'}; int jinzhi, idx; long long shu; int main(){ scanf("%d", &jinzhi); scanf("%s", str); int len = strlen(str); for(int i = 0; i < len; i++) { if(str[i] >= '0' && str[i] <= '9') { shu = shu * jinzhi + str[i] - '0'; } else { shu = shu * jinzhi + (str[i] - 'A' + 10); } } scanf("%d", &jinzhi); long long shang; do { shang = shu / jinzhi; a[idx++] = shu % jinzhi; shu = shang; } while(shang != 0) ; for(int i = idx -1 ; i >= 0; i--) { printf("%c", c[a[i]]); } return 0; }
11.进制转换 -其他(2-16)转10
http://iai.sh.cn/problem/468
#include<bits/stdc++.h> using namespace std; //定义数组并把需要转换的进制数放入数组 int bs[] = {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; //1.十进制转其他进制 2.转换对应进制后判断是否为回文数 bool isPalindrome(int ten,int hex){ char ans[1000]={0}; int ci=0; while(ten){ if(ten%hex>=0){//取余数 ans[ci++]=ten%hex-10+'A';//除以对应进制并转换对应字母 }else{ ans[ci++]=ten%hex+'0';//除以对应进制并转换对应字符 } ten/=hex;//除以对应进制 } ci--; bool isPrime=true;//默认是回文数 for(int i=0;i<=ci/2;i++){//比较一半的数据 //第一个和倒数第一个比 第二个和倒数第二个比 if(ans[i]!=ans[ci-i]){//如果有不相等的则一定不是回文数 isPrime=false; break; } } return isPrime; } int main() { int x; cin>>x; bool flag=false; for(int i=0;i<15;i++){//2-16进制分别比较 if(isPalindrome(x,bs[i])){//有一个就符合输出yes flag=true; break; } } if(flag){ cout<<"Yes"; cout<<endl; for(int i=0;i<15;i++){//所有的进制都检查是否为回文数 if(isPalindrome(x,bs[i])){//输出所有是回文数的进制 cout<<bs[i]<<" "; } } }else{ cout<<"No"; } return 0; }
12.进制转换-10转其他(2-16) -确认进制
http://noi.openjudge.cn/ch0113/34/
#include<bits/stdc++.h> using namespace std; int bs[]={2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; int toTen(int b,int x){//b进制 x转10进制 int power=1;//最右边开始处理 第一位2^0=1 int ret=0; while(x>0){ if(x%10>=b){//如果某一位比进制大,就不可能是这个进制 返回-1特殊处理 return -1; } ret =ret+(x%10*power);//当前位取*权值累加到ret x/=10; power=power*b;//每左移一位 power*b } return ret; } int p,q,r; int main(){ cin>>p>>q>>r; for(int i=0;i<15;i++){// 2-16 逐一转10进制 int pt=toTen(bs[i],p); int qt=toTen(bs[i],q); int rt=toTen(bs[i],r); if(pt==-1 || qt==-1 || rt==-1){//如果不可能是某进制 continue continue; } if(pt*qt==rt){//10进制 符号条件 输出 return cout<<bs[i]; return 0; } } cout<<0;//没有return 说明没有符合的 return 0; }
13.分治算法 - 快速幂
【模板】快速幂||取余运算
https://www.luogu.com.cn/problem/P1226
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll fastPower(ll b,ll p,ll k){ if(p==0){ return 1%k; } ll ret = 1; while(p>0){ if(p%2==0){//指数是偶数 p=p/2;//指数/2 b=b*b%k;//底数相乘 }else{//指数是奇数 p=p-1;//变成偶数 ret=ret*b%k;//这一次乘以底数即为原来的数 p=p/2;//变成偶数后指数/2 b=b*b%k;//底数相乘 } } return ret; } int main(){ ll b,p,k; cin>>b>>p>>k; ll ans = fastPower(b,p,k); cout<<b<<"^"<<p<<" mod "<<k<<"="<<ans; }
14.分治算法 - 快速排序
【模板】快速排序
https://www.luogu.com.cn/problem/P1177
#include<bits/stdc++.h> using namespace std; long long a[100010]; int n; void quickSort(long long arr[],int l,int r){ int i=l,j=r; int mid=arr[l+rand()%(r-l+1)];//随机中间值 防止规则数据无法均分 while(i<=j){ while(arr[i]<mid) i++; while(arr[j]>mid) j--; if(i<=j){ swap(arr[i],arr[j]); i++; j--; } } if(l<j) quickSort(arr,l,j); if(i<r) quickSort(arr,i,r); } int main(){ scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&a[i]); } quickSort(a,0,n-1); for(int i=0;i<n;i++){ printf("%d ",a[i]); } }
15.分治算法 - 逆序对
逆序对
https://www.luogu.com.cn/problem/P1908
//实际上归并排序的交换次数就是这个数组的逆序对个数,为什么呢? //归并排序是将数列a[l,h]分成两半a[l,mid]和a[mid+1,h]分别进行归并排序,然后再将这两半合并起来。 //在合并的过程中(设l<=i<=mid,mid+1<=j<=h),当a[i]<=a[j]时,并不产生逆序数;当a[i]>a[j]时,在 //前半部分中比a[i]大的数都比a[j]大,将a[j]放在a[i]前面的话,逆序数要加上mid+1-i。因此,可以在归并 //排序中的合并过程中计算逆序数 #include<bits/stdc++.h> using namespace std; const int N=500010; int a[N],temp[N]; long long ans; int n; //合并 void merge(int l,int m,int r){ int i=l; int j=m+1; int k=l; while(i<=m && j<=r){ if(a[i]>a[j]){ temp[k++]=a[j++]; //本次去除右半部分一个数,前半部分比a[i]大的个数都可以组成一个,所以m-i+1 ans+=m-i+1; }else{ temp[k++]=a[i++]; } } while(i<=m) temp[k++]=a[i++]; while(j<=r) temp[k++]=a[j++]; for(int i=l;i<=r;i++){ a[i]=temp[i]; } } //拆分 void divide(int l,int r){ if(l<r){ int m=(l+r)/2; divide(l,m); divide(m+1,r); merge(l,m,r); } } int main(){ cin>>n; for(int i=0;i<n;i++){ cin>>a[i]; } divide(0,n-1); cout<<ans; return 0; }
15.1分治算法-归并排序
https://www.cnblogs.com/myeln/articles/13927369.html
#include<bits/stdc++.h> using namespace std; int a[1001],b[1001]; /** * */ void merge(int arr1[],int l,int mid,int r,int arr2[]){ int i=l,j=mid+1,k=l; while(i<=mid && j<=r){//左右两部分追一比较,记录小的到临时数组 if(arr1[i]<arr1[j]){ arr2[k++] = arr1[i++]; }else { arr2[k++] = arr1[j++]; } } //两边数据可能出现不平衡,上面while循环结束可能出现一边元素没放入临时数组情况 //左边没放完按顺序放,到此已经拍好序了 //递归到最后,要么1个元素,要么2个元素,肯定上面while循环已排序或就一个元素加入 while(i<=mid){ arr2[k++] = arr1[i++]; } //右边没放完按顺序放,到此已经拍好序了 while(j<=r){ arr2[k++] = arr1[j++]; } for(i=l;i<=r;i++){ arr1[i] = arr2[i]; } cout<<endl; } void mergeSort(int arr1[],int l,int r,int arr2[]){ //基本情况 if(l==r) return; //原问题分解 int mid=l+(r-l)/2; //解决子问题 mergeSort(arr1,l,mid,arr2); mergeSort(arr1,mid+1,r,arr2); //合并子问题 merge(arr1,l,mid,r,arr2); } int main(){ int a[100],n; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&a[i]); } mergeSort(a,0,n-1,b); for(int i=0;i<n;i++){ printf("%d ",a[i]); } }
16.排序 - 冒泡排序
#include<bits/stdc++.h> void bubbleSort(int arr[],int n){ for(int i=0;i<n-1;i++){ for(int j=0;j<n-1;j++){ if(arr[j]>arr[j+1]){ int temp=arr[j]; arr[j]=arr[j+1]; arr[j+1]=temp; } } } } int main(){ int a[100],n; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&a[i]); } bubbleSort(a,n); for(int i=0;i<n;i++){ printf("%d ",a[i]); } }
17.排序 - 选择排序
#include<bits/stdc++.h> void selectSort(int arr[],int n){ for(int i=0;i<n-1;i++){ int x=i; for(int j=i+1;j<=n;j++){ if(arr[j]<arr[x]){ x=j; } } int temp=arr[i]; arr[i]=arr[x]; arr[x]=temp; } } int main(){ int a[100],n; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&a[i]); } selectSort(a,n); for(int i=0;i<n;i++){ printf("%d ",a[i]); } }
18.排序 - 计数排序
比赛组卷
http://iai.sh.cn/problem/461
#include<bits/stdc++.h> using namespace std; //定义抽取题数n和题库总数k int n,k; //定义计数排序数组a 方便输出暂存数组b int a[100000],b[100000]; //当前输入数temp 累加重复数ans int temp,ans; int main(){ cin>>n>>k; for(int i=0;i<n;i++){//组A卷 cin>>temp;//输入题号到变量temp a[temp]++;//题号做为下标,对应元素值加1 } for(int i=0;i<n;i++){//组B卷 cin>>temp;//输入题号到变量temp a[temp]++;//题号做为下标,对应元素值加1 } //如果有重复题 题号对应数组元素的值为2 a[temp]++ 两次 for(int i=0;i<=k;i++){ if(a[i]==2){//统计有组卷两次的 ans++; b[ans]=i;//放入b数组 } } cout<<ans<<endl; for(int i=1;i<=ans;i++){ cout<<b[i]<<" "; } }
18.1排序 - sort排序
https://www.luogu.com.cn/problem/P1093
#include<bits/stdc++.h>
using namespace std;
struct stx{
int yw,sx,yy;//yw 语文成绩,sx数学成绩, yy英语成绩
int sum,no;//总分,学号
}score[501];
//排序规则
//按总分从大到小
//总分相同按语文从大到小
//总分和语文相同 按学号从小到大
int cmp(stx x1,stx x2){
if(x1.sum!=x2.sum) return x1.sum>x2.sum;
if(x1.yw!=x2.yw) return x1.yw>x2.yw;
return x1.no<x2.no;
}
int main(){
int n;
cin>>n;
//读取数据到数据结构体
for(int i=1;i<=n;i++){
cin>>score[i].yw>>score[i].sx>>score[i].yy;
score[i].sum=score[i].yw+score[i].sx+score[i].yy;
score[i].no=i;
}
//sort从第一个开始的n个人排序
sort(score+1,score+n+1,cmp);
//取前5人
for(int i=1;i<=5;i++){
cout<<score[i].no<<" "<<score[i].sum<<endl;
}
}
19.搜索 dfs
迷宫
https://www.luogu.com.cn/problem/P1605
#include<bits/stdc++.h> using namespace std; int n,m,coun=0,t; int sx,sy,fx,fy; int mp[6][6];//标记是否为障碍物 0为障碍物 1为无障碍物 int vis[6][6]={0};//全为没走过 int dx[4]={0, 0,1,-1}; int dy[4]={1,-1,0, 0}; int b,c;//障碍坐标数 void dfs(int x,int y){ //到达退出 退出条件x==fx && y==fy coun累加 if(x==fx && y==fy){ coun++; return; } //四个方向深度搜索 for(int i=0;i<=3;i++){ //判断mp mp[x+dx[i]][y+dy[i]]==1 是否有障碍物 vis[x+dx[i]][y+dy[i]]==0是否走过 if(mp[x+dx[i]][y+dy[i]]==1&&vis[x+dx[i]][y+dy[i]]==0){ //标记为已走过 vis[x][y]=1; //继续深度搜索x+dx[i] ,y+dy[i] dfs(x+dx[i],y+dy[i]); //回溯一步 vis[x][y]=0; } } } int main(){ cin>>n>>m>>t; cin>>sx>>sy>>fx>>fy; vis[sx][sy]=1;//开始位置第一步走 //所有的标记为无障碍物 mp 二维数组都为1 for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ mp[i][j]=1; } } //把障碍物标记处理 循环对应有障碍物mp位置设置为0 for(int i=1;i<=t;i++){ int tx,ty; cin>>tx>>ty; mp[tx][ty]=0; } dfs(sx,sy);//开始搜索 printf("%d",coun); return 0; }
20.搜索 bfs
填涂颜色
https://www.luogu.com.cn/problem/P1162
#include<bits/stdc++.h> using namespace std; int xx[]={0,1,0,-1}; int yy[]={1,0,-1,0}; int mp[40][40]; bool vis[40][40]; int n; int main(){ cin>>n; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ scanf("%d",&mp[i][j]); } } queue<int> x; queue<int> y; x.push(0); y.push(0); vis[0][0]=1; while(!x.empty()){ for(int i=0;i<4;i++){ int dx=x.front()+xx[i]; int dy=y.front()+yy[i]; if(dx>=0 && dx<=n+1 && dy>=0 && dy<=n+1 && mp[dx][dy]==0 && !vis[dx][dy]){ x.push(dx); y.push(dy); vis[dx][dy]=1; } } x.pop(); y.pop(); } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(mp[i][j]==0 && vis[i][j]==0){ cout<<2; }else{ cout<<mp[i][j]; } cout<<" "; } cout<<endl; } return 0; }
21 01背包
https://www.cnblogs.com/myeln/articles/14672861.html
装箱问题
https://www.luogu.com.cn/problem/P1049
#include<bits/stdc++.h> using namespace std; //dp数组每个元素可看作为当前下标体积的箱子 int dp[20001],w[31];//dp[i]当前体积最大存放物品数量 w每个物品重量 int main(){ int v,n;//v箱子体积 总n个物品 cin>>v>>n; for(int i=1;i<=n;i++)//读取每个物品的体积 cin>>w[i]; for(int i=1;i<=n;i++){//每个物品 模拟放到不同箱子 //v个箱子 从大到小放-dp[j-w[i]] 为不包含本物品的最大值,否则就包含了本物品最大值 for(int j=v;j>=0;j--){ if(w[i]<=j){//体积比当前箱子体积小,才可以放入 //dp[j] 不放入本次体积最大值 dp[j-w[i]]+w[i] 放入本次体积最大值 //dp[j-w[i]] 除本次对应小箱子最大价值 j-w[i]除本次的箱子的体积 dp[j]=max(dp[j],dp[j-w[i]]+w[i]); } } } cout<<v-dp[v];//总体积 - 本箱子放入物品最大体积 return 0; }
采药
https://www.luogu.com.cn/problem/P1048
#include <bits/stdc++.h> using namespace std; int t,m;//可采药时间 草药数目 int w[101], c[101];//w 每株采药花费时间 c每株采药价值 int dp[1001];//i时间内采药最大价值 所有整数都计算 1-1001 int main(){ scanf("%d %d", &t, &m); for(int i=1; i <=m; i++) { scanf("%d %d", &w[i], &c[i]); } for(int i=1;i<=m;i++){ //从t递减累加最大 可以保证dp[j-w[i]未计算本次 for(int j=t;j>=0;j--) { if(w[i]<=j){ // dp[j] 不采最大价值,dp[j-w[i]] + c[i] 采药最大价值 // dp[j-w[i]] 除了本次以外最大价值,j-w[i] 扣除本次时间,c[i]本次价值 dp[j] = max(dp[j], dp[j-w[i]] + c[i]); } } } printf("%d", dp[t]); return 0; }
开心的金明
https://www.luogu.com.cn/problem/P1060
#include<bits/stdc++.h> using namespace std; //v数组为money,w数组为重要度,dp数组 int v[30],w[30],dp[50000]; int n,m;//n是总钱数 m是总物品个数, int main(){ cin>>n>>m;//输入 for(int i=1;i<=m;i++){ cin>>v[i]>>w[i]; w[i]*=v[i];//w数组在这里意义变为总收获(重要度*money) } for(int i=1;i<=m;i++){ for(int j=n;j>=0;j--){//注意从n开始 if(j>=v[i]){ dp[j]=max(dp[j],dp[j-v[i]]+w[i]); } } } cout<<dp[n]<<endl;//背包大小为n时最大值 return 0; }
01背包
初赛模拟2 完善程序1
22 完全背包
https://www.cnblogs.com/myeln/articles/14724764.html
总分
https://www.luogu.com.cn/problem/P2722
#include<iostream> using namespace std; int x,y; //t每种类型需要时间 p每种类型获得分数 int t[10002],p[10002]; //前i种题目,tj时间内获得分数 int dp[10002]; int main(){ int m,n; cin>>m>>n;//m竞赛时间 n是指题目种类 for(int i=1;i<=n;i++){ //pi i类题获得分数 ti 类题花费时间 cin>>p[i]>>t[i]; } for(int i=1;i<=n;i++){ //前i种种类,j时间内获得最大分数 //每种类可以多次累加,比如只有一种时 //i=1 j=8 t[1]=4 dp[8]=dp[4]+p[1] --dp[4]即为p[1] for(int j=t[i];j<=m;j++){ dp[j]=max(dp[j],dp[j-t[i]]+p[i]); } } //dp[m] m时间内所有种类获得最大分数 cout<<dp[m]; return 0; }
疯狂的采药
https://www.luogu.com.cn/problem/P1616
#include <bits/stdc++.h> using namespace std; //t用来采药的时间 m山洞里草药的种类 int t,m; //采第i种草药需要的时间和价值 int a[10002], b[10002]; //前i种采药 j时间内采药最大的价值 long long dp[10000002]; int main(){ scanf("%d %d", &t,&m); for(int i=1; i <=m; i++) { scanf("%d %d", &a[i], &b[i]); } for(int i = 1; i <= m; i++){ //前i种采药 j时间内采药最大的价值 for(int j = a[i]; j <= t; j++) { //加入价值变大则加入 dp[j] = max(dp[j],dp[j-a[i]] + b[i]); } } //所有种类草药 t时间内采药的最大价值 printf("%lld", dp[t]); return 0; }
23 多重背包
初赛模拟3阅读2
1.最大公约数
#include<bits/stdc++.h>
using namespace std;
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
int main(){
cout<<gcd(4,6);
return 0;
}
2.最小公倍数
#include<bits/stdc++.h>
using namespace std;
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
int main(){
// a*b/gcd(a,b)
cout<<4*6/gcd(4,6);
return 0;
}
作者:newcode 更多资源请关注纽扣编程微信公众号

从事机器人比赛、机器人等级考试、少儿scratch编程、信息学奥赛等研究学习

浙公网安备 33010602011771号