Пытаюсь впихнуть невпихуемое задачу на битмаски, где можно брать либо 1 либо 2 предмета, с TL до 4000ms
Пока смотрю, сколько времени будет работать максимальный тест. Вот тут код:
#include <bits/stdc++.h>
using namespace std;
int main() {
int p = 24; // Кол-во предметов максимум
int al = (1 << p); // Кол-во масок, "1" - предмет под i-тым битом уже взят
int vec[1 << 24]; // Ответы к подзадачам
int vec2[1 << 24];
int inf = 1000000005;
fill(vec, vec + al, inf);
vector<int> kek;
vec[0] = 0;
for(int z = 1; z < al; z++) {
// Вместо перебора 24 * (24 - 1) / 2 значений перебираем
// места, где есть биты
kek.clear();
for(int ss = 0; ss < 24; ss++)
if(z & (1 << ss))
kek.push_back(ss);
// Оптимальный ответ
int last = inf;
for(int a = 0; a < kek.size(); a++) {
int az = z - (1 << kek[a]);
if(last > vec[az] + 1)
last = vec[az] + 1;
for(int b = a + 1; b < kek.size(); b++) {
int bz = az - (1 << kek[b]);
if(last > vec[bz] + 2)
last = vec[bz] + 2;
}
}
//vec[z] = last;
}
}
Предполагается, что в переменной last сохраняется оптимальный ответ (конечно, не просто vec[xx]+2, а по нужной формуле расстояний между предметами kek[a] и kek[b])
Запуск codeforces этого кода в GNU C++ работает за 1309ms (погрешность +-15ms)
Если раскомментировать строку "vec[z] = last;" это работает за 4040ms
Наконец, если завести новый массив vec2 и заменить строку на "vec2[z] = last;", это работает практически за то же время что в первый раз — от 1294ms до 1310ms
Вот это прикол! Какое его научное обоснование?
Ну що тут казатi
Возможно, или из-за кэша, или из-за оптимизатора.
Возможно, что попеременное обращение к
vec[az/bz]
иvec[z]
очень хорошо убивает кеш процессора, и код постоянно обращается к сравнительно медленной оперативной памяти. Если предположение верное, то при постепенном уменьшении размера массива наступит момент, когда он целиком поместится в кеше, и эффект внезапно пропадёт.Если
vec2
нигде после присваивания не используется, то оптимизатор его уберёт, и будет то же, что и в первом случае.Вообще для чистоты эксперимента программе следует считывать данные и выводить результат. Потому что иначе компилятор может подумать "ой, да эта программа же ничего не делает, давай-ка соптимизируем её в
return 0;
".Ага, после кода "cout << vec2[0];" все стало на свои место — больше 4000ms :)
Последний абзац — я так по первости один раз попался. :))) Меняю на release — моментально считает 1,000,000 primes. Ставлю debug — вообще не дождаться. Я долго глючил, пока понял, что оптимизатор просто на фиг выбросил мои расчёты, потому что ничего не выводилось на экран и никуда не записывалось :))
Попробуйте локально у себя запустить с различными параметрами оптимизации.
Кажется условие ниже никогда не выполнится.
Учитывая, что компилятор знает все значения в vec (0 и куча inf) и то что он не меняется, я бы на его месте выпилил этот цикл совсем.
Изменил, все как прежде
Как уже писали выше: если вы переменную заполняете, но не используете — компилятор может выпилить её. Кажется если вы добавите
cout << vec2[al - 1] << endl;
в конце, то получите те же "тормоза", что и в случае сvec
.