zoukankan      html  css  js  c++  java
  • Atcoder Regular 097 相邻球交换目的递增DP

    A

    /*Huyyt*/
    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const ll LLmaxn = 2e18;
    string a;
    int K;
    string str[10000000];
    int pop = 0;
    map<string, int> mp;
    int main()
    {
            cin >> a;
            cin >> K;
            for (int i = 0; i <= 25 && pop < K; i++)
            {
                    for (int j = 0; j < a.size(); j++)
                    {
                            if (a[j] == 'a' + i)
                            {
                                    string now = "";
                                    for (int k = j; k < min((int)a.size(), j + K); k++)
                                    {
                                            now += a[k];
                                            if (!mp[now])
                                            {
                                                    str[++pop] = now;
                                                    //cout<<now<<endl;
                                                    mp[now]++;
                                            }
                                    }
                            }
                    }
            }
            sort(str + 1, str + pop + 1);
            cout << str[K] << endl;
            return 0;
    }
    View Code

    B

    给1-N的一个排列 再给你M个Xi,Yi表示Xi与Yi位置的数可以无限次交换

    解:

    并查集 因为交换次数是无线的所以在一个集内的数字可以到其他任何一个位置

    /*Huyyt*/
    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const ll LLmaxn = 2e18;
    const int N = 100005;
    int par[N];
    void init(int n)
    {
            for (int i = 0; i <= n; i++)
            {
                    par[i] = i;
            }
    }
    int find(int x)
    {
            return par[x] == x ? x : par[x] = find(par[x]);
    }
    void unite(int x, int y)
    {
            x = find(x);
            y = find(y);
            if (x != y)
            {
                    par[x] = y;
            }
    }
    int num[N];
    int where[N];
    int a, b;
    int main()
    {
            int n;
            int m;
            cin >> n;
            cin >> m;
            init(n);
            int anser = 0;
            for (int i = 1; i <= n; i++)
            {
                    cin >> num[i];
                    where[num[i]] = i;
            }
            for (int i = 1; i <= m; i++)
            {
                    cin >> a >> b;
                    unite(a,b);
            }
            for (int i = 1; i <= n; i++)
            {
                    if (find(where[i]) == find(i))
                    {
                            anser++;
                    }
            }
            cout << anser << endl;
            return 0;
    }
    View Code

    C

    有2N个球 一半是白的 一半是黑的 每个白球和黑球上都有一个数字 分别都可以组成1-N

    在一次操作内你可以交换相邻的两个球 问你最少需要多少次操作使得从左到右 白球和黑球各自都是递增序

     解:

    dp[i][j]表示现在在(i+j)的位置有1-i白球且1-j黑球正确排序所需要的最少操作数

    pre[kind][i][j]表示第kind种的球在第i个位置及之前标号不小于j的有几个

    /*Huyyt*/
    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const ll LLmaxn = 2e18;
    const int N = 2e3 + 5;
    int n;
    int s;
    int dp[N][N];
    int pos[2][N];
    int pre[2][N * 2][N];
    void init()
    {
            for (int kind = 0; kind <= 1; kind++)
            {
                    for (int i = 0; i < s; i++)
                    {
                            for (int j = n - 1; j >= 1; j--)
                            {
                                    pre[kind][i][j - 1] += pre[kind][i][j];
                            }
                    }
                    for (int i = 0; i < s - 1; i++)
                    {
                            for (int j = 0; j < n; j++)
                            {
                                    pre[kind][i + 1][j] += pre[kind][i][j];
                            }
                    }
            }
            for (int i = 0; i <= n; i++)
            {
                    for (int j = 0; j <= n; j++)
                    {
                            dp[i][j] = INT_MAX;
                    }
            }
            dp[0][0] = 0;
    }
    int main()
    {
            cin >> n;
            s = n * 2;
            for (int i = 0; i < s; i++)
            {
                    string ch;
                    cin >> ch;
                    int kind = 1;
                    int x;
                    cin >> x;
                    x--;
                    if (ch[0] == 'W')
                    {
                            kind = 0;
                    }
                    pos[kind][x] = i;
                    pre[kind][i][x]++;
            }
            init();
            for (int i = 0; i <= n; i++)
            {
                    for (int j = 0; j <= n; j++)
                    {
                            if (i < n)
                            {
                                    int p = pos[0][i];
                                    dp[i + 1][j] = min(dp[i + 1][j], dp[i][j] + pre[0][p][i + 1] + pre[1][p][j]);
                            }
                            if (j < n)
                            {
                                    int p = pos[1][j];
                                    dp[i][j + 1] = min(dp[i][j + 1], dp[i][j] + pre[0][p][i] + pre[1][p][j + 1]);
                            }
                    }
            }
            cout << dp[n][n] << endl;
            return 0;
    }
    View Code
  • 相关阅读:
    01、u-boot 打补丁 编译 烧写
    3、JZ2440 按键驱动(中断)
    2、JZ2440 按键驱动(查询)
    1、JZ2440 LED驱动
    004、栈的基本操作
    003、动态顺序表的插入与删除
    002、静态顺序表的插入与删除
    对百度的评价
    关于找水王的思路
    软件市场应用前景
  • 原文地址:https://www.cnblogs.com/Aragaki/p/9031848.html
Copyright © 2011-2022 走看看