2010 универсальное решения NOIP к задаче установить реванш в

Название и включают алгоритмы:

  • Статистические показатели: Getting Started вопрос;
  • Доступ к воде: основные вопросы моделирования;
  • Перехватчики: динамическое программирование, жадное;
  • Три игр: жадная, теория игр.

Статистические показатели

Тема ссылка: Л Гу P1179
Этот вопрос является основным вопросом.
Нам необходимо только открыть переменную \ (CNT \) для статистического \ (2 \) количество вхождений, а \ (L \) к \ (Р & л \) , чтобы пройти каждое число \ (I \) , для \ ( я \) , мы проходим через него всякий не \ (2 \) , и если да, то \ (CNT ++ \) . Окончательный вывод \ (CNT \) может быть.
Коды являются следующими:

#include <bits/stdc++.h>
using namespace std;
int cnt, L, R;
void solve(int a) {
    while (a) {
        if (a % 10 == 2) cnt ++;
        a /= 10;
    }
}
int main() {
    cin >> L >> R;
    for (int i = L; i <= R; i ++) solve(i);
    cout << cnt << endl;
    return 0;
}

проблемы Подземные воды

Тема ссылка: Л Гу P1190
Этот вопросом является стандартным названием моделирования, который имитирует процесс , мы открываем воду.
Мы делаем \ (ш [я] \) обозначает \ (я \) индивидуальное время открытия воды, которое требуется, так \ (т [я] \) указывает на то, что текущий раздел \ (я \) отводы подключены к воде люди берут хорошую воду момент.
Таким образом , мы сначала пройти , чем \ (\ 0) в \ (м-1 \) координаты \ (I \) , так что \ (T [I] = W [I] , \) (до \ (т \) индивидуальный приоритет оккупации краны),
то мы имеем из \ (т \) к \ (п-1 \) , чтобы пересечь координаты \ (I \) , для первого \ (I \) физическое лицо, он должен вставить позиции должны быть все \ (W [J] (0 \ ле J \ л м) \) наименьший из \ (\ J) , мы предполагаем , что минимум \ (ш [J] \) координирует соответствующий бит \ (\ ID) , то первый\ (\ Я) физические лица будут вставлены в первом \ (идентификатор \) позицию. Мы делаем \ (T [ID] + = ш [я] \) к (Это означает , что первая \ (я \) индивиды в первый \ (идентификатор \) местах продолжают открывать воду).
Окончательный ответ, что все \ (т [I] (0 \ ле я \ л м) \) одним из крупнейших (самый крупный \ (т [г] \) соответствует последнему человеку , чтобы заложить заложить время).
Коды являются следующими:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 10010;
int n, m, cnt, w[maxn], t[maxn];
int main() {
    cin >> n >> m;
    if (m > n) m = n;
    for (int i = 0; i < n; i ++) cin >> w[i];
    for (int i = 0; i < m; i ++) t[i] = w[i];
    for (int i = m; i < n; i ++) {
        int id = 0; // id用于表示当前这一轮最早结束的那个队列对应的id
        for (int j = 0; j < m; j ++) if (t[j] < t[id]) id = j;
        t[id] += w[i];
    }
    int ans = 0;
    for (int i = 0; i < m; i ++) ans = max(ans, t[i]);
    cout << ans << endl;
    return 0;
}

Тем не менее, приведенный выше код не является оптимальным, его время , сложность \ (O (n- \ CDOT м) \) .

Для узнал кучу (Heap) студентов этой структуры данных, мы можем использовать кучу , чтобы решить эту проблему на него. Мы можем поддерживать размер не более чем \ (т \) небольшой корень куча, каждый не извлекали из верхней части элемента \ (т \) , он сказал , что самое быстрое личное время , чтобы заложить в воду, а затем , если кто - то рядом затем (при условии , что номер человека \ (I \) ), мы тогда \ (т + ш [я] \) в стек , пока все из них в стек.
Затем удалить элемент из кучи , в свою очередь, взятой из кучи последнего элемента будет соответствовать последнему человеку , чтобы заложить время воды боя.
Поскольку стек вручную , чтобы получить слишком много хлопот, поэтому мы используем STL контейнеры , предоставляемые нашу очередь приоритета priority_queue для достижения небольшого корня кучи.
Коды являются следующими:

#include <bits/stdc++.h>
using namespace std;
int n, m, w, t, maxt;
priority_queue<int, vector<int>, greater<int> > pq;
int main() {
    cin >> n >> m;
    if (m > n) m = n;
    for (int i = 0; i < m; i ++) {
        cin >> w;   // w表示第i个人打开水所耗费的时间
        pq.push(w);
    }
    for (int i = m; i < n; i ++) {
        cin >> w;
        t = pq.top();
        pq.pop();           // 上一个人打好开水
        pq.push(t + w);     // 下一个人继续打开水
    }
    while (!pq.empty()) {
        maxt = pq.top();
        pq.pop();
    }
    cout << maxt << endl;
    return 0;
}

перехватчиков

Тема ссылка: Л Гу P1158
этот вопрос связан с алгоритмами: динамическое программирование, жадная. Но в основном один найти закон субъекта (учитель не нашел закон, я должен был найти закон после того, как видящие объяснения Сплетница).
Решение проблемы обратитесь к разделу «Annie 007«Luogu Бо-офф: https://www.luogu.org/blog/Annie-007/solution-p1158
этот вопрос мы должны сначала очистить все ракетные перехватчики вместо того , чтобы быть система № 1 перехвачены система № 2
мы видим , этот вопрос объема данных 10 ^ 5, предположительно NlogN сложность, думать о упорядочивании
давайте рассмотрим оптимальное решение, оптимальное решение в системе №1 , конечно , дистанцироваться первым остановился возле
Если номер 1 в бар с его дальней ракетой , если, на самом деле, между прочим ножка ближней ракеты перехвачена ,
если мы помещаем все ракеты в соответствии с расстоянием № 1 в порядке возрастания, думая только наш знать наверняка находится под номером 1 перехватывает приставка, суффикс к остальной части № 2 ,
то мы перечислим то , что этот префикс и суффикс точка демаркации (точка отсечения мы определили здесь в качестве префикса последней точки)
№ 1 систему стоимость лечения лучше количество префиксов граница номер точки от 1 систему
системы 2 на этот раз уже не может видеть то , чей суффикс является самым большим для расчета стоимости, то нам нужен массив предварительной обработки, и пусть D [я] = я и содержит первый позади вести максимальное расстояние бомбы
кода следующим образом :

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
long long X1, Y1, X2, Y2, x, y, d[maxn];
int n;
struct Node {
    long long s1, s2;   // s1表示到(x1,y1)的距离;s2表示到(x2,y2)的距离
} a[maxn];
bool cmp(Node a, Node b) {
    return a.s1 < b.s1;
}
int main() {
    cin >> X1 >> Y1 >> X2 >> Y2 >> n;
    for (int i = 0; i < n; i ++) {
        cin >> x >> y;
        a[i].s1 = (x - X1) * (x - X1) + (y - Y1) * (y - Y1);
        a[i].s2 = (x - X2) * (x - X2) + (y - Y2) * (y - Y2);
    }
    sort(a, a+n, cmp);
    for (int i = n-1; i >= 0; i --) {
        d[i] = max(a[i].s2 , d[i+1]);
    }
    long long ans = LONG_LONG_MAX;
    for (int i = 0; i < n; i ++)
        ans = min(ans, a[i].s1 + d[i+1]);
    cout << ans << endl;
    return 0;
}

Три игры

Тема ссылка: Л Гу P1199
этот вопрос включает в себя алгоритмы: жадные, теории игр.
Блог решение проблемы с wjyyy: https://www.luogu.org/blog/wjyyy/solution-p1199
этой проблемы , несмотря на длинное название, в основном , чтобы доказать правильность жадных.

Во- первых, мы замечаем , что в этой задаче, компьютер жадный , то есть не сказать, независимо от того , что кандидаты, можно будет избрать людей , понимающих значение максимума. Мысль здесь может подумать , теорию игр, потому что два человека один и та же цель. Но немного анализ , что люди всегда получают лучшее.

Поскольку мы выбрали будет рассматриваться как процесс спаривания, так что после выборов будут II, II первой строка и II-столбец таблицы строки и столбцы наши, в своих собственных строках и столбцах находится на пересечении их генералов а. Эта форма является симметричной.

Анализ проб может быть изучен, всегда оптимальным решением для каждой строки рейтинга (чистовой) второй по величине крупной. Другими словами, самая большая группа компьютеров , что каждая строка вряд ли позволит вам выбрать руку. После того, как вы выбрали самую большую группу , в которой компьютер всегда может обрабатывать первую половину ограбили, так что самая большая группа в каждой строке невозможно избрано. И мы хотим доказать, что наибольшие времена крупных и средних будет иметь возможность выбрать.

Когда мы выбрали второй по величине средней и большой линии, компьютер, без сомнения, самый большой из линии к избранным.

На данный момент мы имеем самый большой и среднего размера половины к другой раз сопровождал его. Теперь, когда мы получили люди, чтобы получить максимально возможную пару генералов, как убедиться, что компьютер не получает больше, чем их собственные генералы делать? Как можно видеть, существует негласное соглашение, чем текущее значение больше некоторых генералов в наибольшей позиции в других рядах, (при условии, что компьютер достаточно умен), если выборы пошли к компьютеру, что положение, Иже верху, и взять его на линии. И компьютер не такой умный, это позволит избежать вы можете избрать максимум генералов, на этот раз можно разделить на обсуждение.

В Выберите компьютер Генералы два эффекта: во- первых, пересекаются с оригинальной зеленой линией, если пересечение и зеленая линия будет непосредственно определять группу генералов, когда люди в состоянии остановить. Но теперь мы можем гарантировать значение пересечения линии и зеленой линии меньше , чем ответы некоторых людей. Данные об обратном: Если ответ на это значение , чем люди (пятиконечная звезда) , чтобы быть меньше большого треугольника, то второй по величине средней и большой это значение, то это значение не представляется возможным в этом диапазоне, и если значение этого человека больше , чем треугольник , что треугольник является самым крупным средним и большим. Таким образом, пересечение с зеленой линии не будет больше , чем пятиконечная звезда.

Второй эффект заключается в том, что не пересекаются, и зеленая линия. Для некоторых непересекающихся и зеленой линии, до тех пор, как люди выходят, чтобы захватить самый большой компьютер, компьютер не может захватить каждую строку в самом крупный.

Таким образом, будь то человек или компьютер не может захватить каждую строку , что самые большой, по жадному, людям предпочитают идти на второй по величине элемента каждой строки в самом большом будет иметь возможность выбирать, в это время может помешать компьютеру идти на большие выборы элементы. В то же время люди не будут терять.
Коды блога заключаются в следующем:

#include<cstdio>
#include<algorithm>
using std::sort;
int a[510][510];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<n;i++)
        for(int j=i+1;j<=n;j++)
        {
            scanf("%d",&a[i][j]);
            a[j][i]=a[i][j];
        }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        sort(a[i]+1,a[i]+1+n);
        ans=ans>a[i][n-1]?ans:a[i][n-1];//选出排名第二中最大的那个
    }
    printf("1\n%d\n",ans);//一定有解
    return 0;
}

Тогда я понял , когда я посмотрел на код , прежде чем забил 90 из окончательной , если я не судить мой счет и забить робота, и я забил прямой выход «1», я был в состоянии АС,,
но во второй опытной группе когда данные моя программа , кажется, измеряется моим Забей меньше роботов, так вот именно сейчас я могу получить AC код, но мое текущее мышление является обратной пятой и шестой строках, а не предпоследний 3,4 линия. Интересно , тогда есть время тщательно о том думать, стремиться решить эту проблему как можно скорее.
Коды следующим образом (хотя AC , но результаты окончательного вывода вопросов до сих пор имеются в большом количестве):

#include <bits/stdc++.h>
using namespace std;
const int maxn = 550;
int g[maxn][maxn], n, belong[maxn];
vector<int> vec, ans1, ans2;

int get_company(int id) {
    int tmp1 = 0, tmp2 = 0;
    for (int i = 1; i <= n; i ++) {
        if (id == i || belong[i]) continue;
        if (g[id][i] > tmp1) { tmp2 = tmp1; tmp1 = g[id][i]; }
        else if (g[id][i] > tmp2) tmp2 = g[id][i];
    }
    for (vector<int>::iterator it = ans1.begin(); it != ans1.end(); it ++) {
        int u = *it;
        tmp2 = max(tmp2, g[id][u]);
    }
    return tmp2;
}

bool cmp1(int a, int b) {
    return get_company(a) > get_company(b);
}

bool cmp2(int a, int b) {
    int sz = ans1.size();
    int tmp1 = 0, tmp2 = 0;
    for (int i = 0; i < sz; i ++) {
        tmp1 = max(tmp1, g[ ans1[i] ][a]);
        tmp2 = max(tmp2, g[ ans1[i] ][b]);
    }
    return tmp1 > tmp2;
}

int main() {
    cin >> n;
    for (int i = 1; i <= n; i ++) {
        for (int j = i+1; j <= n; j ++) {
            cin >> g[i][j];
            g[j][i] = g[i][j];
        }
    }
    for (int i = 1; i <= n; i ++) vec.push_back(i);
    for (int i = 1; i <= n; i ++) {
        if (i % 2) {
            sort(vec.begin(), vec.end(), cmp1);
            ans1.push_back(vec[0]);
            belong[ vec[0] ] = 1;
            vec.erase(vec.begin());
        }
        else {
            sort(vec.begin(), vec.end(), cmp2);
            ans2.push_back(vec[0]);
            belong[ vec[0] ] = 2;
            vec.erase(vec.begin());
        }
    }
    int res1 = 0, res2 = 0;
    for (int i = 0; i < n/2; i ++)
        for (int j = i+1; j < n/2; j ++) {
            res1 = max(res1, g[ ans1[i] ][ ans1[j] ]);
            res2 = max(res2, g[ ans2[i] ][ ans2[j] ]);
        }
    // puts(res1 >= res2 ? "1" : "0");
    // if (res1 >= res2) cout << res1 << endl;
    puts("1");
    cout << res1 << endl;
    return 0;
}

Автор: zifeiy

рекомендация

отwww.cnblogs.com/codedecision/p/11710636.html
рекомендация