ICPC North Central NA Contest 2017 (Part of the solution)

table of Contents

to sum up:

Stoichiometry

1. The main idea of ​​the topic:

2. Analysis:

3. Code implementation:

Smooth Array

1. The main idea of ​​the topic:

2. Analysis:

3. Code implementation:


to sum up:

I'm so good , this one should be AK...

Stoichiometry

1. The main idea of ​​the topic:

Chemical equation balance

2. Analysis:

Direct Gaussian elimination. Since the title says that it contains a unique minimum solution, it means that there is one and only one free element. Enumerate the values ​​of the free elements so that each coefficient is an integer.

3. Code implementation:

#include <bits/stdc++.h>
using namespace std;

const double eps = 1e-8;

int len;
struct node
{
    int sgn, n;
    string ele[20];
    int num[20];
}s[20];

int cnt;
map <string, int> id;

double a[10][10];
int x[10];

void read()
{
    while(cin >> s[len].sgn >> s[len].n && s[len].sgn && s[len].n)
    {
        for(int i = 0; i < s[len].n; ++i)
        {
            cin >> s[len].ele[i] >> s[len].num[i];
            if(!id.count(s[len].ele[i]))
                id[s[len].ele[i]] = cnt++;
        }
        ++len;
    }
}

void build()
{
    for(int i = 0; i < len; ++i)
    {
        for(int j = 0; j < s[i].n; ++j)
        {
            a[id[s[i].ele[j]]][i] += s[i].num[j] * s[i].sgn;
        }
    }
}

int gauss()
{
    int c, r;
    for(c = 0, r = 0; c < len; ++c)
    {
        int t = r;
        for(int i = r; i < cnt; ++i)
        {
            if(fabs(a[i][c]) > fabs(a[t][c]))   t = i;
        }
        if(fabs(a[t][c]) < eps) continue;
        for(int i = c; i < len; ++i) swap(a[t][i], a[r][i]);
        for(int i = len - 1; i >= c; --i) a[r][i] /= a[r][c];
        for(int i = 0; i < cnt; ++i)
        {
            if(i == r)  continue;
            if(fabs(a[i][c]) > eps)
            {
                for(int j = len - 1; j >= c; --j)
                {
                    a[i][j] -= a[r][j] * a[i][c];
                }
            }
        }
        ++r;
    }
}

bool check(int x)
{
    double s;
    for(int i = 0; i < len; ++i)
    {
        s = -a[i][len - 1] * x;
        if(abs(int(s + eps) - s) > eps)
            return 0;
    }
    return 1;
}

void work()
{
    for(int i = 1; ; ++i)
    {
        if(check(i))
        {
            for(int j = 0; j < len - 1; ++j)
                printf("%d ", (int)(-a[j][len - 1] * i + eps));
            printf("%d\n", i);
            return;
        }
    }
}

int main()
{
    read();
    build();
    gauss();
    work();
    return 0;
}

Smooth Array

1. The main idea of ​​the topic:

For an array a of length n, each number can now be modified to any value, so that the sum of every k consecutive numbers is s, and find the minimum number of modifications.

2. Analysis:

It is easy to know that a[i] == a[i + j * k].

Then the numbers can be divided into k groups, and the problem is transformed into making the elements in the group equal, and the sum of the elements in each group is the minimum modification times of s.

Obviously DP, let dp[i][j] mean that the first i group is considered, and the sum of the elements of the first i group is the maximum number of times of no modification of s.

The final answer is n-dp[k-1][s].

State calculation is very simple, too lazy to talk about it.

3. Code implementation:

#include <bits/stdc++.h>
using namespace std;

const int M = (int)5e3;
const int inf = 0x3f3f3f3f;

int a[M + 5];
int cnt[M + 5];
vector <int> v;
int dp[2][M + 5];

int main()
{
    int n, k, s;
    scanf("%d %d %d", &n, &k, &s);
    for(int i = 0; i < n; ++i)
        scanf("%d", &a[i]);
    memset(dp, -inf, sizeof(dp));
    for(int i = 0; i < k; ++i)
    {
        v.clear();
        memset(cnt, 0, sizeof(cnt));
        for(int j = 0; i + j * k < n; ++j)
        {
            if(cnt[a[i + j * k]] == 0)
            {
                v.push_back(a[i + j * k]);
            }
            ++cnt[a[i + j * k]];
        }
        if(i == 0)
        {
            for(int j = 0; j <= s; ++j)
                dp[i & 1][j] = cnt[j];
        }
        else
        {
            int mx = -inf;
            for(int j = 0; j <= s; ++j)
            {
                dp[i & 1][j] = -inf;
                for(auto x: v)
                {
                    if(j >= x)
                        dp[i & 1][j] = max(dp[i & 1][j], dp[i - 1 & 1][j - x] + cnt[x]);
                }
                mx = max(mx, dp[i - 1 & 1][j]);
                dp[i & 1][j] = max(dp[i & 1][j], mx);
            }
        }
    }
    printf("%d\n", n - dp[k - 1 & 1][s]);
    return 0;
}

 

Guess you like

Origin blog.csdn.net/The___Flash/article/details/104598915