Блог пользователя Egor

Автор Egor, 16 лет назад, По-русски
4 августа в 15:00 MSD состоится очередной TopCoder SRM
  • Проголосовать: нравится
  • +12
  • Проголосовать: не нравится

16 лет назад, скрыть # |
 
Проголосовать: нравится +15 Проголосовать: не нравится
 это почти как праздник=)
спасибо за напоминание!
удачи всем;)
16 лет назад, скрыть # |
 
Проголосовать: нравится +3 Проголосовать: не нравится
А чем member srm отличается от просто srm?
16 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Эх, похоже не получится написать. На работе дел много
16 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
В чем идея Div-1 500? Судя по ограничениям в 15 бутылок, здесь надо использовать дп по маскам. Но вот только как...
  • 16 лет назад, скрыть # ^ |
     
    Проголосовать: нравится +1 Проголосовать: не нравится
    Расскажу свою идею, не хватило времени дописать, вероятно неправильная, у меня вообще туго с опровержением себя)

    Считаем дп по маскам, f[i]--максимальный профит от маски i бутылок.
    Также препроцессингом за 2^15 просчитаем массив a[i]--профит, если мы разольем маску i бутылок так, чтобы было максимально полных бутылок, одна частично(от 0 до c) заполненная, а остальные пустые.

    И как считаем--если у нас есть ответ для маски i, то мы перебираем все остальные маски, не пересекающиеся с i(для оптимизации я считал в новой "цепочке" мы будем всегда использовать самый левый нулевой бит маски i) и обновляем ответ f[mask | newmask]=max(f[mask |newmask],f[mask]+a[newmask])
  • 16 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    Вот решение. К сожалению, придумал я его уже после окончания контеста:
    public class KiwiJuice {
    public int theProfit(int C, int[] a, int[] p) {
    int n = a.length;
    int[] s = new int[1 << n];
    int[] q = new int[1 << n];
    for (int i = 0; i < (1 << n); i++) {
    q[i] = q[i >> 1] + (i & 1);
    for (int j = 0; j < n; j++) {
    if (((i >> j) & 1) != 0)
    s[i] += a[j];
    }
    }
    int[] ans = new int[1 << n];
    for (int i = 0; i < (1 << n); i++) {
    for (int j = i; j != 0; j = (j - 1) & i) {
    ans[i] = Math.max(ans[i], ans[i - j] + p[C] * (s[j] / C) + p[s[j] % C] + p[0] * (q[j] - 1 - s[j] / C));
    }
    }
    return ans[(1 << n) - 1];
    }
    }

  • 16 лет назад, скрыть # ^ |
     
    Проголосовать: нравится +3 Проголосовать: не нравится
    Основная идея в том что после переливания из одной бутылки в другую, у нас получится либо одна полная бутылка либо одна пустая. Переливать в пустую или переливать из полной бутылки нет никакого смысла, просто емкости двух бутылок поменяются местами.

    Фактически получается мы считаем максимальную прибыль, если мы уже использовали какой-то множество I бутылок и причем в одной активной бутылке из использованных находится K литров сока причем мы еще не посчитали прибыль за эту бутылку, объем сока еще может измениться в ней.
    Тогда для пересчета мы просто смотрим бутылку J которую мы не использовали и с ней мы можем сделать несколько операций:
    (dm[I][K] мы уже посчитатли. J не принадлежит I)
    -просто использовать, т.е. добавить прибыль за эту бутылку
     dm[I+(1 << J)][K] = max(dm[I+(1 << J)][K], prices[bottle[J]] + dm[I][K]);
    -сделать ее активной
     dm[I+(1 << J)][bottle[J]] = max(dm[I+(1 << J)][bottle[J]], prices[K] + dm[I][K]);
    -перелить в активную бутылку
    если bottle[j] + k < C
     dm[I + (1 << J)][botlle[J] + K] = max(dm[I + (1 << J)][botlle[J] + K], dm[I][K] + prices[0]);
    иначе
     dm[I + (1 << J)][botlle[J] + K - C] = max(dm[I + (1 << J)][botlle[J] + K], dm[I][K] + prices[C]);
16 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Как в Div-2 делать вторую задачу?
  • 16 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    суть в том что у нас каждый раз получаются числи вида: (2^n)*init+(2^n-1)
  • 16 лет назад, скрыть # ^ |
     
    Проголосовать: нравится +1 Проголосовать: не нравится
    Я писал bfs+map.
    • 16 лет назад, скрыть # ^ |
       
      Проголосовать: нравится 0 Проголосовать: не нравится
      Я также делал. Допустил глупейшую ошибку в итоге зацикливалось=(
      В практисе сразу же сдал, когда увидел оплошность
  • 16 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    Я так решал:

    1) x*4+3 и x*8+7 коммутируют между собой, то есть неважно в каком порядке выполнять операции, можно считать, что сначала мы делаем сколько-то операций первого типа, а потом сколько-то второго.

    2) ясно, что мы просто выполняет все операции в кольце вычетов по модулю 10^9+7. это всем известное простое число, ура =) значит мы можем делить на 4 и на 8.

    сделаем 100 000 обратных операций первого типа от нуля, запишем в мап, а потом 100 000 операций другого типа от числа init.
  • 16 лет назад, скрыть # ^ |
     
    Проголосовать: нравится +9 Проголосовать: не нравится
    В двоичной записи 4*x+3 это добавление двух единиц справа, 8*x+7 это добавление трёх единиц. Посмотрим сколько надо добавить единиц чтобы получить остаток 0, делаем x_new = 2*x+1 где-то 300000 раз. Пусть через K итераций мы получили остаток 0, значит ответ K/3 + (K%3==0?0:1). Только начинать надо сразу с двух итераций.
16 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
map это что?
16 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
ето масив , но вместо обыкновенных индексов, выступают практически все типы данных С++.
Например:... map< string,int >a ...; Дальше в коде можна использовать a["one"] и прочее. Вообщем много хорошых вещей дает map.(поисчи в нете)