zoukankan      html  css  js  c++  java
  • Codeforces 946 课程表背包DP 数位DFS构造

    A

    B

    给你A,B 两个数      1.a=0 OR b=0 break      2.a>=2b a=a-2b        3.b>=2a b=b-2a

    如果只是单纯模拟肯定会超时

    只需要简化 a>=2b --> a%=2b    b>=2a --> b%=2a就可以

    #include <bits/stdc++.h>
    #define PI acos(-1.0)
    #define mem(a,b) memset((a),b,sizeof(a))
    #define TS printf("!!!
    ")
    #define pb push_back
    #define inf 1e9
    //std::ios::sync_with_stdio(false);
    using namespace std;
    //priority_queue<int,vector<int>,greater<int>> que; get min
    const double eps = 1.0e-10;
    const double EPS = 1.0e-4;
    typedef pair<int, int> pairint;
    typedef long long ll;
    typedef unsigned long long ull;
    //const int maxn = 3e5 + 10;
    const int  maxm = 300;
    const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}};
    //priority_queue<int, vector<int>, less<int>> que;
    //next_permutation
    ll mod = 3e7;
    int main()
    {
            ll a, b;
            cin >> a >> b;
            int flag = 0;
            while (!flag)
            {
                    ll moda = 1LL * 2 * a;
                    ll modb = 1LL * 2 * b;
                    if (a == 0 || b == 0)
                    {
                            break;
                    }
                    if (a >= 1LL * 2 * b)
                    {
                            a = a % modb;
                            continue;
                    }
                    else
                    {
                            if (b >= 1LL * 2 * a)
                            {
                                    b = b % moda;
                                    continue;
                            }
                            else
                            {
                                    break;
                            }
                    }
                    //cout << a << " " << b << endl;
            }
            cout << a << " " << b << endl;
    }
    View Code

    C

    子序列和子串要分清楚。。

    #include <bits/stdc++.h>
    #define PI acos(-1.0)
    #define mem(a,b) memset((a),b,sizeof(a))
    #define TS printf("!!!
    ")
    #define pb push_back
    #define inf 1e9
    //std::ios::sync_with_stdio(false);
    using namespace std;
    //priority_queue<int,vector<int>,greater<int>> que; get min
    const double eps = 1.0e-10;
    const double EPS = 1.0e-4;
    typedef pair<int, int> pairint;
    typedef long long ll;
    typedef unsigned long long ull;
    //const int maxn = 3e5 + 10;
    const int  maxm = 300;
    const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}};
    //priority_queue<int, vector<int>, less<int>> que;
    //next_permutation
    ll mod = 3e7;
    int num[100005];
    int zimu[30];
    int len;
    int flag=0;
    void dfs(int x, int now)
    {
            if(now==26)
            {
                    flag=1;
                    return;
            }
            for (int i = x; i <= len; i++)
            {
                    if (num[i] <= now)
                    {
                            num[i] = now;
                            dfs(i + 1, now + 1);
                            break;
                    }
            }
    }
    int main()
    {
            for (int i = 0; i <= 25; i++)
            {
                    zimu[i] = i;
            }
            string a;
            cin >> a;
            flag = 0;
            len = a.size();
            if (len <= 25)
            {
                    cout << -1 << endl;
                    return 0;
            }
            for (int i = 0; i < len; i++)
            {
                    num[i + 1] = a[i] - 'a';
            }
            dfs(1, 0);
            if (flag)
            {
                    for (int i = 1; i <= len; i++)
                    {
                            char ch = 'a';
                            ch += num[i];
                            cout << ch;
                    }
            }
            else
            {
                    cout << -1 << endl;
            }
    }
    View Code

    D

    贪心不可做 正解是背包DP

    其中dp[i][j]表示前 i 天删去 j 节课所需要的最少上课时间

    dp方程是 dp[i][j+k]=min(dp[i][j+k],dp[i-1][j]+ke[k]) 其中ke[i]表示的是当天除去i节课所需要最少上课时间

    ke[i]需要用前缀和来算

    #include <bits/stdc++.h>
    #define PI acos(-1.0)
    #define mem(a,b) memset((a),b,sizeof(a))
    #define TS printf("!!!
    ")
    #define pb push_back
    #define inf 1e9
    //std::ios::sync_with_stdio(false);
    using namespace std;
    //priority_queue<int,vector<int>,greater<int>> que; get min
    const double eps = 1.0e-10;
    const double EPS = 1.0e-4;
    typedef pair<int, int> pairint;
    typedef long long ll;
    typedef unsigned long long ull;
    const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}};
    //priority_queue<int, vector<int>, less<int>> que;
    //next_permutation
    const int maxn = 505;
    int pre[maxn];
    char f[maxn];
    int ke[maxn];
    int dp[maxn][maxn];
    int main()
    {
            int n, m, K;
            cin >> n >> m >> K;
            for (int i = 1; i <= n; i++)
            {
                    mem(dp[i], 0x3f3f3f3f);
                    mem(ke, 0x3f3f3f3f);
                    scanf("%s", f + 1);
                    for (int j = 1; j <= m; j++)
                    {
                            pre[j] = pre[j - 1] + (f[j] == '1');
                    }
                    if (pre[m] <= K)
                    {
                            ke[pre[m]] = 0;
                    }
                    for (int j = 1; j <= m; j++)
                    {
                            for (int k = j; k <= m; k++)
                            {
                                    int len = pre[m] - pre[k] + pre[j - 1];
                                    if (len <= K)
                                    {
                                            ke[len] = min(ke[len], k - j + 1);
                                    }
                            }
                    }
                    for (int j = 0; j <= K; j++)
                    {
                            for (int k = 0; j + k <= K; k++)
                            {
                                    dp[i][j + k] = min(dp[i][j + k], dp[i-1][j] + ke[k]);
                            }
                    }
            }
            cout << dp[n][K] << endl;
    }
    View Code

    E

    给你一个数字,求一个比当前数字小的 最大的漂亮数字

    (漂亮数:所以在当前数中出现的数出现的次数为偶数次)

    当长度为奇数时 答案明显是len-1个9

    偶数时就需要搜索 找出最后面的字典序可以比原序列小的地方

    如果空格数大于当前出现次数为奇数的数的个数就输出9

    因为整体是偶数个数 0-9都是构造的成双出现的 所以一定满足

    如果找不到 就输出len-2个9;  (小的数例如10不用特殊处理 因为题目保证答案一定存在)

    #include <bits/stdc++.h>
    #define PI acos(-1.0)
    #define mem(a,b) memset((a),b,sizeof(a))
    #define TS printf("!!!
    ")
    #define pb push_back
    #define inf 1e9
    //std::ios::sync_with_stdio(false);
    using namespace std;
    //priority_queue<int,vector<int>,greater<int>> que; get min
    const double eps = 1.0e-10;
    const double EPS = 1.0e-4;
    typedef pair<int, int> pairint;
    typedef long long ll;
    typedef unsigned long long ull;
    const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}};
    //priority_queue<int, vector<int>, less<int>> que;
    //next_permutation
    const int maxn = 2e5 + 5;
    int cnt[maxn][10];
    char f[maxn];
    int n;
    int len;
    void getans()
    {
            int i, j, k;
            for (i = len; i >= 1; i--)
            {
                    for (j = (int)(f[i] - '0') - 1; j >= (i == 1); j--)
                    {
                            int now = 0;
                            for (k = 0; k <= 9; k++)
                            {
                                    now += cnt[i - 1][k] ^ (k == j);
                            }
                            if (now <= len - i)
                            {
                                    for (k = 1; k < i; k++)
                                    {
                                            cout << f[k];
                                    }
                                    cout << j;
                                    for (k = 1; k <= len - i - now; k++)
                                    {
                                            cout << 9;
                                    }
                                    for ( k = 9; k >= 0; k--)
                                    {
                                            if (cnt[i - 1][k] ^ (k == j))
                                            {
                                                    cout << k;
                                            }
                                    }
                                    cout << endl;
                                    return ;
                            }
                    }
            }
            for (i = 1; i <= len - 2 + (len % 2); i++)
            {
                    cout << 9;
            }
            cout << endl;
    }
    int main()
    {
            cin >> n;
            while (n--)
            {
                    scanf("%s", f + 1);
                    len = strlen(f + 1);
                    for (int i = 0; i <= 9; i++)
                    {
                            cnt[0][i] = 0;
                    }
                    for (int i = 1; i <= len; i++)
                    {
                            int now = f[i] - '0';
                            for (int j = 0; j <= 9; j++)
                            {
                                    cnt[i][j] = cnt[i - 1][j] ^ (j == now);
                            }
                    }
                    getans();
            }
    }
    View Code
  • 相关阅读:
    104. 二叉树的最大深度
    Shopping HDU
    Fibonacci again and again HDU
    Brave Game HDU
    Being a Good Boy in Spring Festival HDU
    88. 合并两个有序数组
    26. 删除排序数组中的重复项
    快速幂
    Rectangles(2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1))扫描线+线段树
    Liars(2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1))差分法
  • 原文地址:https://www.cnblogs.com/Aragaki/p/8573597.html
Copyright © 2011-2022 走看看