zoukankan      html  css  js  c++  java
  • #YBT整理 递推(三)

    重点题目:

    1、P1197 :山区建小学

    2、P1195 :判断整除

    3、P1192 :放苹果

    4、P1312 :【例3.4】昆虫繁殖

    5、P1313 :【例3.5】位数问题

    6、P1188 :菲波那契数列(2)

    P1195 :判断整除

    题目描述

    一个给定的正整数序列,在每个数之前都插入+号或一号后计算它们的和。比如序列: 1、2、4共有8种可能的序列:

    (+1) + (+2) + (+4) = 7
    (+1) + (+2) + (-4) = -1
    (+1) + (-2) + (+4) = 3
    (+1) + (-2) + (-4) = -5
    (-1) + (+2) + (+4) = 5
    (-1) + (+2) + (-4) = -3
    (-1) + (-2) + (+4) = 1
    (-1) + (-2) + (-4) = -7
    

    所有结果中至少有一一个可被整数k整除,我们则称此正整数序列可被k整除。例如上述序列可以被3、5、7整除,而不能被2、4、6、......除。注意: 0、一3、一6、一9... ...都可以认为是3的倍数。

    【输入】

    输入的第一行包含两个数: N(2 《N 《 10000)和k(2 《k《 100),其中N代表一共有N个数, k代表被除数。第二行给出序列中的N个整数,这些整数的取值范围都0到10000之间(可 能重复)

    【输出】

    如果此正整数序列可被k整除,则输出YES,否则输出NO。(注意: 都是大写字母)

    【输入样例】

    3 2
    1 2 4
    

    【输出样例】

    NO
    

    思路

    用a数组存储每一步可能粗线的每一种和,因为k < 100 所以只用开100的就行,存储方式类似于桶。
    b数组辅助存储。a[i]就相当于当前操作是否可能出现i,可能为true,不可能为false。每一次更新的时候就从为true的i进行加减操作。具体看代码。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
     long long n;
    bool a[1000],b[1000];
     long long k;
    int main(){
        cin >> n;
        cin >> k;
        for( long long i = 1;i <= n; i++){
             long long x;
            cin >> x;
            if(i == 1){
                b[x%k] = 1;
                 long long y = -x;
                while(y < 0) y += k;
                b[y] = 1;
                for( long long j = 1;j < k; j++){
                    a[j] = b[j];
                }
                for(int j = 0;j < k; j++) cout << a[j] << ' ';
                cout << endl;
                continue;
            }
            x %= k;
            memset(b,0,sizeof b);
            for( long long j = 0;j < k; j++){
                if(a[j]){
                    b[(j+x) % k] = 1;
                    b[(j-x+k) % k] = 1;
                }
            }
            for( long long j = 0;j < k; j++){
                a[j] = b[j];
                cout << a[j] <<  ' ';
            }
            cout << endl; 
        }
        if(a[0] == 1){
            cout << "YES" << endl;
            return 0;
        }
        cout << "NO" << endl;
        return 0;
    }
    

    P1196 :踩方格

    题目描述

    有一个方格矩阵,矩阵边界在无穷远处。我们做如下假设:

    a、每走一步时,只能从当前方格移动一格,走到某个相邻的方格上;

    b、走过的格子立即塌陷无法再走第二次;

    c、只能向北、东、西三个方向走;

    请问:如果允许在方格矩阵上走n步,共有多少种不同的方案。2种走法只要有一步不一 样,即被认为是不同的方案。

    【输入】

    允许在方格上行走的步数n(n<=20)。

    【输出】

    计算出的方案数量。

    【输入样例】

    2
    

    【输出样例】

    7
    

    思路

    每次只能往三个方向走,因为是20的数据范围,所以直接暴力dfs

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    int n;
    int vis[50][50];
    int ans = 0;
    void dfs(int x,int y,int step){
        if(step == n){
            ans++;
            return;
        }
        if(!vis[x+1][y]){
            vis[x+1][y] = 1;
            dfs(x+1,y,step+1);
            vis[x+1][y] = 0;
        }
        if(!vis[x][y+1]){
            vis[x][y+1] = 1;
            dfs(x,y+1,step+1);
            vis[x][y+1] = 0;
        }
        if(!vis[x][y-1]){
            vis[x][y-1] = 1;
            dfs(x,y-1,step+1);
            vis[x][y-1] = 0;
        }
    }
    int main(){
        cin >> n;
        vis[0][25] = 1;
        dfs(0,25,0);
        cout << ans << endl;
        return 0;
    }
    

    P1197 :山区建小学

    题目描述

    政府在某山区修建了一一条道路,恰好穿越总共m个村庄的每个村庄-一次,没有回路或交叉,任意两个村庄只能通过这条路来往。已知任意两个相邻的村(d_{i})(为正整数),其中,0<i<m。为了提高山区的文化素质,政府又决定从m个村中选择n个村建小学(设0<n≤m<500)。请根据给定的m、n以及所有相邻村庄的距离,选择在哪些村庄建小学,才使得所有村到最近小学的距离总和最小,计算最小值。

    【输入】

    第1行为m和n,其间用空格间隔

    第2行为m一1个整数,依次表示从一端到另一端的相邻村庄的距离,整数之间以空格间隔。例如:

    10 3
    2 4 6 5 2 4 3 1 3
    

    表示在10个村庄建3所学校。第1个村庄与第2个村庄距离为2,第2个村庄与第3个村庄距离为4,第3个村庄与第4个村庄距离为6,.... 第9个村庄到第10个村庄的距离为3。

    【输出】

    各村庄到最近学校的距离之和的最小值。

    【输入样例】

    10 2
    3 1 3 1 1 1 1 1 3
    

    【输出样例】

    18
    

    思路

    就先初始化几个数组:dis[i][j]表示i到j的距离,s[i][j]表示从i到j建一所学校的最短花费(可以证明学校一定要建立在ij的正中间),最后上动态规划:f[i][j]表示前i个学校建立j所学校的最小化费,每次从小到大枚举k。

    [f[i][j] = min(f[i][j],f[k][j-1] + s[k+1][i]) ]

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    int n,m;
    int dis[600][600];
    int s[600][600];
    int f[600][600];
    int add[600];
    int cnt_dis(int x,int y){
        int tot = 0;
        int mid = (x+y) >> 1;
        for(int i = x;i <= y; i++){
            tot += dis[mid][i];
        }
        return tot;
    }
    int main(){
        cin >> n;
        cin >> m;
        for(int i = 2;i <= n; i++){
            int x;
            cin >> x;
            add[i] = add[i-1] + x;
        }
        for(int i = 1;i <= n; i++){
            for(int j = i;j <= n; j++){
                dis[i][j] = dis[j][i] = add[j] - add[i];
            }
        }
        for(int i = 1;i <= n; i++){
            for(int j = i;j <= n; j++){
                s[i][j] = s[j][i] = cnt_dis(i,j);
            }
        }
        memset(f,1e9+7,sizeof f);
        f[0][0] = 0;
        for(int i = 1;i <= n; i++){
            for(int j = 1;j <= m; j++){
                if(i < j) {f[i][j] = 0;continue;}
                for(int k = j-1;k <= n; k++){
                    f[i][j] = min(f[i][j],f[k][j-1]+s[k+1][i]);
                }
            }
        }
        cout << f[n][m] << endl;
        return 0;
    }
    
  • 相关阅读:
    队列分类梳理
    停止线程
    Docker和Kubernetes
    Future、Callback、Promise
    Static、Final、static final
    线程池梳理
    TCP四次挥手
    http1.0、http1.x、http 2和https梳理
    重排序
    java内存模型梳理
  • 原文地址:https://www.cnblogs.com/Cao-Yucong/p/12468274.html
Copyright © 2011-2022 走看看