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;
}

 

posted @ 2021-08-02 23:26  new-code  阅读(260)  评论(0)    收藏  举报