void Bin(int level, int count){ if (count > H) return; int i; if (level == N){ if (count == H) print(); return; } Output[level] = 0; Bin(level + 1, count); Output[level] = 1; Bin(level + 1, count + 1); }
int main() { int n; scanf("%d",&n); printf("%d",Bin(n)); }
SearchBins::SearchBins() { // HTmin,HTmax,MHTmin,MHTmax,NJetsmin,NJetsmax,BTagsmin,BTagsmax // NJets 4,6 BTags=0 // fixed ht Njets btags all MHT bins bins_.push_back( Bin(500,800,200,500,4,6,-1,0) ); bins_.push_back( Bin(800,1200,200,500,4,6,-1,0) ); bins_.push_back( Bin(1200,99999,200,500,4,6,-1,0) ); bins_.push_back( Bin(500,1200,500,750,4,6,-1,0) ); bins_.push_back( Bin(1200,99999,500,750,4,6,-1,0) ); bins_.push_back( Bin(800,99999,750,9999,4,6,-1,0) ); // NJewts 7,8 BTags=0 bins_.push_back( Bin(500,800,200,500,7,8,-1,0) ); bins_.push_back( Bin(800,1200,200,500,7,8,-1,0) ); bins_.push_back( Bin(1200,99999,200,500,7,8,-1,0) ); bins_.push_back( Bin(500,1200,500,750,7,8,-1,0) ); bins_.push_back( Bin(1200,99999,500,750,7,8,-1,0) ); bins_.push_back( Bin(800,99999,750,9999,7,8,-1,0) ); // NJewts 9,9999 BTags=0 bins_.push_back( Bin(500,800,200,500,9,9999,-1,0) ); bins_.push_back( Bin(800,1200,200,500,9,9999,-1,0) ); bins_.push_back( Bin(1200,99999,200,500,9,9999,-1,0) ); bins_.push_back( Bin(500,1200,500,750,9,9999,-1,0) ); bins_.push_back( Bin(1200,99999,500,750,9,9999,-1,0) ); bins_.push_back( Bin(800,99999,750,9999,9,9999,-1,0) ); // NJets 4,6 BTags=1 // fixed ht Njets btags all MHT bins bins_.push_back( Bin(500,800,200,500,4,6,1,1) ); bins_.push_back( Bin(800,1200,200,500,4,6,1,1) ); bins_.push_back( Bin(1200,99999,200,500,4,6,1,1) ); bins_.push_back( Bin(500,1200,500,750,4,6,1,1) ); bins_.push_back( Bin(1200,99999,500,750,4,6,1,1) ); bins_.push_back( Bin(800,99999,750,9999,4,6,1,1) ); // NJewts 7,8 BTags=0 bins_.push_back( Bin(500,800,200,500,7,8,1,1) ); bins_.push_back( Bin(800,1200,200,500,7,8,1,1) ); bins_.push_back( Bin(1200,99999,200,500,7,8,1,1) ); bins_.push_back( Bin(500,1200,500,750,7,8,1,1) ); bins_.push_back( Bin(1200,99999,500,750,7,8,1,1) ); bins_.push_back( Bin(800,99999,750,9999,7,8,1,1) ); // NJewts 9,9999 BTags=1 bins_.push_back( Bin(500,800,200,500,9,9999,1,1) ); bins_.push_back( Bin(800,1200,200,500,9,9999,1,1) ); bins_.push_back( Bin(1200,99999,200,500,9,9999,1,1) ); bins_.push_back( Bin(500,1200,500,750,9,9999,1,1) ); bins_.push_back( Bin(1200,99999,500,750,9,9999,1,1) ); bins_.push_back( Bin(800,99999,750,9999,9,9999,1,1) ); // NJets 4,6 BTags=2 // fixed ht Njets btags all MHT bins bins_.push_back( Bin(500,800,200,500,4,6,2,2) ); bins_.push_back( Bin(800,1200,200,500,4,6,2,2) ); bins_.push_back( Bin(1200,99999,200,500,4,6,2,2) ); bins_.push_back( Bin(500,1200,500,750,4,6,2,2) ); bins_.push_back( Bin(1200,99999,500,750,4,6,2,2) ); bins_.push_back( Bin(800,99999,750,9999,4,6,2,2) ); // NJewts 7,8 BTags=2 bins_.push_back( Bin(500,800,200,500,7,8,2,2) ); bins_.push_back( Bin(800,1200,200,500,7,8,2,2) ); bins_.push_back( Bin(1200,99999,200,500,7,8,2,2) ); bins_.push_back( Bin(500,1200,500,750,7,8,2,2) ); bins_.push_back( Bin(1200,99999,500,750,7,8,2,2) ); bins_.push_back( Bin(800,99999,750,9999,7,8,2,2) ); // NJewts 9,9999 BTags=2 bins_.push_back( Bin(500,800,200,500,9,9999,2,2) ); bins_.push_back( Bin(800,1200,200,500,9,9999,2,2) ); bins_.push_back( Bin(1200,99999,200,500,9,9999,2,2) ); bins_.push_back( Bin(500,1200,500,750,9,9999,2,2) ); bins_.push_back( Bin(1200,99999,500,750,9,9999,2,2) ); bins_.push_back( Bin(800,99999,750,9999,9,9999,2,2) ); // NJets 4,6 BTags=>3 // fixed ht Njets btags all MHT bins bins_.push_back( Bin(500,800,200,500,4,6,3,9999) ); bins_.push_back( Bin(800,1200,200,500,4,6,3,9999) ); bins_.push_back( Bin(1200,99999,200,500,4,6,3,9999) ); bins_.push_back( Bin(500,1200,500,750,4,6,3,9999) ); bins_.push_back( Bin(1200,99999,500,750,4,6,3,9999) ); bins_.push_back( Bin(800,99999,750,9999,4,6,3,9999) ); // NJewts 7,8 BTags=>3 bins_.push_back( Bin(500,800,200,500,7,8,3,9999) ); bins_.push_back( Bin(800,1200,200,500,7,8,3,9999) ); bins_.push_back( Bin(1200,99999,200,500,7,8,3,9999) ); bins_.push_back( Bin(500,1200,500,750,7,8,3,9999) ); bins_.push_back( Bin(1200,99999,500,750,7,8,3,9999) ); bins_.push_back( Bin(800,99999,750,9999,7,8,3,9999) ); // NJewts 9,9999 BTags=>3 bins_.push_back( Bin(500,800,200,500,9,9999,3,9999) ); bins_.push_back( Bin(800,1200,200,500,9,9999,3,9999) ); bins_.push_back( Bin(1200,99999,200,500,9,9999,3,9999) ); bins_.push_back( Bin(500,1200,500,750,9,9999,3,9999) ); bins_.push_back( Bin(1200,99999,500,750,9,9999,3,9999) ); bins_.push_back( Bin(800,99999,750,9999,9,9999,3,9999) ); std::cout<<"Loaded bins: "<<bins_.size()<<std::endl; for(unsigned int i=0; i<bins_.size();i++) { usedBin_.push_back(0); } }
void solveCase(){ Bin(0, 0); }
u8 DS18B20Read(u8 pin, u8 num, u8 resolution, TEMPERATURE * t) { u8 res, busy = 0; u8 temp_lsb, temp_msb; switch (resolution) { case RES12BIT: res = Bin(01100000); break; // 12-bit resolution case RES11BIT: res = Bin(01000000); break; // 11-bit resolution case RES10BIT: res = Bin(00100000); break; // 10-bit resolution case RES9BIT: res = Bin(00000000); break; // 9-bit resolution default: res = Bin(00000000); break; // 9-bit resolution /// NB: The power-up default of these bits is R0 = 1 and R1 = 1 (12-bit resolution) } DS18B20Configure(pin, num, 0, 0, res); // no alarm if (OneWireReset(pin)) return FALSE; if (num == SKIPROM) { // Skip ROM, address all devices OneWireWrite(pin, SKIPROM); } else { // Talk to a particular device DS18B20MatchRom(pin, num); } OneWireWrite(pin, CONVERT_T); // Start temperature conversion while (busy == 0) // Wait while busy ( = bus is low) busy = OneWireRead(pin); if (OneWireReset(pin)) return FALSE; if (num == SKIPROM) { // Skip ROM, address all devices OneWireWrite(pin, SKIPROM); } else { // Talk to a particular device DS18B20MatchRom(pin, num); } OneWireWrite(pin, READ_SCRATCHPAD);// Read scratchpad temp_lsb = OneWireRead(pin); // byte 0 of scratchpad : temperature lsb temp_msb = OneWireRead(pin); // byte 1 of scratchpad : temperature msb OneWireReset(pin); // Calculation // --------------------------------------------------------------------- // Temperature Register Format // BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0 // LS BYTE 2^3 2^2 2^1 2^0 2^-1 2^-2 2^-3 2^-4 // BIT15 BIT14 BIT13 BIT12 BIT11 BIT10 BIT9 BIT8 // MS BYTE S S S S S 2^6 2^5 2^4 // S = SIGN if (temp_msb >= Bin(11111000)) // test if temperature is negative { t->sign = 1; temp_msb -= Bin(11111000); } else { t->sign = 0; } t->integer = temp_lsb >> 4; // fractional part is removed, it remains only integer part t->integer |= (temp_msb << 4); // integer part from temp_msb is added t->fraction = 0; // fractional part ( if (BitRead(temp_lsb, 0)) t->fraction += 625; if (BitRead(temp_lsb, 1)) t->fraction += 1250; if (BitRead(temp_lsb, 2)) t->fraction += 2500; if (BitRead(temp_lsb, 3)) t->fraction += 5000; t->fraction /= 100; // two digits after decimal return TRUE; }
SearchBins::SearchBins() { // HTmin,HTmax,MHTmin,MHTmax,NJetsmin,NJetsmax,BTagsmin,BTagsmax // NJets 4,6 BTags=0 // fixed ht Njets btags all MHT bins // bins_.push_back( Bin(500,800,200,500,4,6,-1,0) ); // bins_.push_back( Bin(800,1200,200,500,4,6,-1,0) ); // bins_.push_back( Bin(1200,99999,200,500,4,6,-1,0) ); // bins_.push_back( Bin(500,1200,500,750,4,6,-1,0) ); // bins_.push_back( Bin(1200,99999,500,750,4,6,-1,0) ); // bins_.push_back( Bin(800,99999,750,9999,4,6,-1,0) ); // // NJewts 7,8 BTags=0 // bins_.push_back( Bin(500,800,200,500,7,8,-1,0) ); // bins_.push_back( Bin(800,1200,200,500,7,8,-1,0) ); // bins_.push_back( Bin(1200,99999,200,500,7,8,-1,0) ); // bins_.push_back( Bin(500,1200,500,750,7,8,-1,0) ); // bins_.push_back( Bin(1200,99999,500,750,7,8,-1,0) ); // bins_.push_back( Bin(800,99999,750,9999,7,8,-1,0) ); // // NJewts 9,9999 BTags=0 // bins_.push_back( Bin(500,800,200,500,9,9999,-1,0) ); // bins_.push_back( Bin(800,1200,200,500,9,9999,-1,0) ); // bins_.push_back( Bin(1200,99999,200,500,9,9999,-1,0) ); // bins_.push_back( Bin(500,1200,500,750,9,9999,-1,0) ); // bins_.push_back( Bin(1200,99999,500,750,9,9999,-1,0) ); // bins_.push_back( Bin(800,99999,750,9999,9,9999,-1,0) ); // // NJets 4,6 BTags=1 // // fixed ht Njets btags all MHT bins // bins_.push_back( Bin(500,800,200,500,4,6,1,1) ); // bins_.push_back( Bin(800,1200,200,500,4,6,1,1) ); // bins_.push_back( Bin(1200,99999,200,500,4,6,1,1) ); // bins_.push_back( Bin(500,1200,500,750,4,6,1,1) ); // bins_.push_back( Bin(1200,99999,500,750,4,6,1,1) ); // bins_.push_back( Bin(800,99999,750,9999,4,6,1,1) ); // // NJewts 7,8 BTags=0 // bins_.push_back( Bin(500,800,200,500,7,8,1,1) ); // bins_.push_back( Bin(800,1200,200,500,7,8,1,1) ); // bins_.push_back( Bin(1200,99999,200,500,7,8,1,1) ); // bins_.push_back( Bin(500,1200,500,750,7,8,1,1) ); // bins_.push_back( Bin(1200,99999,500,750,7,8,1,1) ); // bins_.push_back( Bin(800,99999,750,9999,7,8,1,1) ); // // NJewts 9,9999 BTags=1 // bins_.push_back( Bin(500,800,200,500,9,9999,1,1) ); // bins_.push_back( Bin(800,1200,200,500,9,9999,1,1) ); // bins_.push_back( Bin(1200,99999,200,500,9,9999,1,1) ); // bins_.push_back( Bin(500,1200,500,750,9,9999,1,1) ); // bins_.push_back( Bin(1200,99999,500,750,9,9999,1,1) ); // bins_.push_back( Bin(800,99999,750,9999,9,9999,1,1) ); // NJets 4,6 BTags=2 // fixed ht Njets btags all MHT bins bins_.push_back( Bin(500,800,200,500,4,6,2,2) ); bins_.push_back( Bin(800,1200,200,500,4,6,2,2) ); bins_.push_back( Bin(1200,99999,200,500,4,6,2,2) ); bins_.push_back( Bin(500,1200,500,750,4,6,2,2) ); bins_.push_back( Bin(1200,99999,500,750,4,6,2,2) ); bins_.push_back( Bin(800,99999,750,9999,4,6,2,2) ); // NJewts 7,8 BTags=2 bins_.push_back( Bin(500,800,200,500,7,8,2,2) ); bins_.push_back( Bin(800,1200,200,500,7,8,2,2) ); bins_.push_back( Bin(1200,99999,200,500,7,8,2,2) ); bins_.push_back( Bin(500,1200,500,750,7,8,2,2) ); bins_.push_back( Bin(1200,99999,500,750,7,8,2,2) ); bins_.push_back( Bin(800,99999,750,9999,7,8,2,2) ); // NJewts 9,9999 BTags=2 bins_.push_back( Bin(500,800,200,500,9,9999,2,2) ); bins_.push_back( Bin(800,1200,200,500,9,9999,2,2) ); bins_.push_back( Bin(1200,99999,200,500,9,9999,2,2) ); bins_.push_back( Bin(500,1200,500,750,9,9999,2,2) ); bins_.push_back( Bin(1200,99999,500,750,9,9999,2,2) ); bins_.push_back( Bin(800,99999,750,9999,9,9999,2,2) ); // NJets 4,6 BTags=>3 // fixed ht Njets btags all MHT bins bins_.push_back( Bin(500,800,200,500,4,6,3,9999) ); bins_.push_back( Bin(800,1200,200,500,4,6,3,9999) ); bins_.push_back( Bin(1200,99999,200,500,4,6,3,9999) ); bins_.push_back( Bin(500,1200,500,750,4,6,3,9999) ); bins_.push_back( Bin(1200,99999,500,750,4,6,3,9999) ); bins_.push_back( Bin(800,99999,750,9999,4,6,3,9999) ); // NJewts 7,8 BTags=>3 bins_.push_back( Bin(500,800,200,500,7,8,3,9999) ); bins_.push_back( Bin(800,1200,200,500,7,8,3,9999) ); bins_.push_back( Bin(1200,99999,200,500,7,8,3,9999) ); bins_.push_back( Bin(500,1200,500,750,7,8,3,9999) ); bins_.push_back( Bin(1200,99999,500,750,7,8,3,9999) ); bins_.push_back( Bin(800,99999,750,9999,7,8,3,9999) ); // NJewts 9,9999 BTags=>3 bins_.push_back( Bin(500,800,200,500,9,9999,3,9999) ); bins_.push_back( Bin(800,1200,200,500,9,9999,3,9999) ); bins_.push_back( Bin(1200,99999,200,500,9,9999,3,9999) ); bins_.push_back( Bin(500,1200,500,750,9,9999,3,9999) ); bins_.push_back( Bin(1200,99999,500,750,9,9999,3,9999) ); bins_.push_back( Bin(800,99999,750,9999,9,9999,3,9999) ); }
HRESULT Update(double deltaTime) { HRESULT hr = S_OK; if (g_endgame) return EndgameUpdate(deltaTime); // TODO: Optimize for cache coherency // We could attempt to store chains of nodes linearly in memory. That would make the update loop for nodes in those chains // super fast (since the most chains could probably fit in one cache line). But it would involve a lot of mem moves and // could introduce some complexity. Since we're already under 1ms average, I'd say let's not do it. // Sort into buckets BeginCounter(&binningCounter); { float pixelsPerVert = float((g_width * g_height) / g_numActiveNodes); float binDiameterPixels = sqrt(pixelsPerVert); // conservative g_binNHeight = binDiameterPixels / g_height; g_binNWidth = binDiameterPixels / g_width; g_binCountX = uint(ceilf(1.0f / g_binNWidth) )+2; // Add a boundary around the outside g_binCountY = uint(ceilf(1.0f / g_binNHeight))+2; uint xiter = g_binUpdateIter % g_numBinSplits; uint yiter = g_binUpdateIter / g_numBinSplits; g_binRangeX[0] = (g_binCountX * xiter/g_numBinSplits) - 1; // Subtract/Add 1 to each of these ranges for a buffer layer g_binRangeX[1] = (g_binCountX * (xiter+1)/g_numBinSplits - 1) + 1; // This buffer layer will be overlap for each quadrant g_binRangeY[0] = (g_binCountY * yiter/g_numBinSplits) - 1; // But without it verts would only target verts in their quadrant g_binRangeY[1] = (g_binCountY * (yiter+1)/g_numBinSplits - 1) + 1; g_binStride = g_numSlots / ((g_binRangeX[1] - g_binRangeX[0] + 1) * (g_binRangeY[1] - g_binRangeY[0] + 1)); int bin; memset(g_slots, EMPTY_SLOT, sizeof(g_slots)); for (uint i = 0; i < g_numNodes; i++) { if (g_nodes[i].attribs.hasChild == true) continue; // Only bin the chompable tails hr = Bin(g_nodes[i].position.getX(), g_nodes[i].position.getY(), &bin); if (FAILED(hr)) // If this bin isn't backed by memory, we can't be a target this frame continue; // Find first empty bin slot for (uint slot = 0; slot < g_binStride; slot++) { if (g_slots[bin*g_binStride + slot] == EMPTY_SLOT) { g_slots[bin*g_binStride + slot] = i; break; } } // If we overflow the bins, the vertex cannot be targeted. Haven't seen any cases yet... } g_binUpdateIter = (g_binUpdateIter+1) % (g_numBinSplits*g_numBinSplits); } EndCounter(&binningCounter); // Determine nearest neighbors BeginCounter(&nearestNeighborCounter); for (uint i = 0; i < g_numNodes; i++) { IFC( FindNearestNeighbor(i) ); } EndCounter(&nearestNeighborCounter); BeginCounter(&positionUpdate); for (uint i = 0; i < g_numNodes; i++) { // Do our memory reads here so we can optimize our access patterns Node& current = g_nodes[i]; Node& target = g_nodes[current.attribs.targetID]; // Get target vector // For optimal precision, pull our shorts into floats and do all math at full precision... float2 targetVec; targetVec.x = target.position.getX() - current.position.getX(); targetVec.y = target.position.getY() - current.position.getY(); float dist = targetVec.getLength(); float2 dir = targetVec; if (dist != 0) dir = dir / dist; // Calculate change in position float2 offset; if (current.attribs.hasParent) { // This controls wigglyness. Perhaps it should be a function of velocity? (static is more wiggly) float parentPaddingRadius = g_tailDist;// + (rand() * 2 - 1)*g_tailDist*0.3f; offset = targetVec - dir * parentPaddingRadius; } else offset = min(targetVec, dir * float(g_speed * deltaTime)); // ... then finally, at the verrrry end, stuff our FP floats into 16-bit shorts current.position.setX(current.position.getX() + offset.x); current.position.setY(current.position.getY() + offset.y); // Check for chomps if (current.attribs.hasParent == false && dist <= g_tailDist) Chomp(i); } EndCounter(&positionUpdate); Cleanup: if (g_numActiveNodes == 1) return EndgameInit(); return hr; }
HRESULT FindNearestNeighbor(short index) { HRESULT hr = S_OK; if (g_nodes[index].attribs.hasParent == true) return S_FALSE; float2 pos = {g_nodes[index].position.getX(), g_nodes[index].position.getY()}; if (Bin(pos.x, pos.y, nullptr) != S_OK) return S_FALSE; // if we're not in a bin backed by memory, just keep our old neighbor int xrange[2] = {int(pos.x/g_binNWidth - 0.5f), int(pos.x/g_binNWidth + 0.5f)}; int yrange[2] = {int(pos.y/g_binNHeight - 0.5f), int(pos.y/g_binNHeight + 0.5f)}; uint minDist = -1; ushort nearest = -1; int bin; do { // Yes, we'll re-iterate over some bins, but the bin rows are stored linearly in memory // So the cache should make this pretty cheap (plus it's only one access since they'll probably be empty) for (int y = yrange[0]; y <= yrange[1]; y++) { for (int x = xrange[0]; x <= xrange[1]; x++) { hr = Bin(x, y, &bin); ASSERT(SUCCEEDED(hr)); // Bin fails if the bin isn't memory backed. for (uint slot = 0; slot < g_binStride; slot++) { // TODO: These large strides are going to kill the cache! // We should probably switch to storing the node indexes linearly with the MSb denoting end of bucket // Then we'd have a separate table to index into this based on bucket // No, that won't work because inserts would be very difficult/expensive. The easiest way would be a linked // list, but that would obviously be super slow. I think I the first try was actually the best ;D ushort target = g_slots[bin*g_binStride + slot]; if (target == EMPTY_SLOT) break; else if (IsValidTarget(target, index)) { uint dist = Distance(g_nodes[index].position, g_nodes[target].position); if (dist < minDist) { minDist = dist; nearest = target; } } } } } if (xrange[0] > g_binRangeX[0]) xrange[0]--; if (xrange[1] < g_binRangeX[1]) xrange[1]++; if (yrange[0] > g_binRangeY[0]) yrange[0]--; if (yrange[1] < g_binRangeY[1]) yrange[1]++; // Do we need this? Could happen if a vert is in a quadrant of it's own if (xrange[1] - xrange[0] == g_binRangeX[1] - g_binRangeX[0] && yrange[1] - yrange[0] == g_binRangeY[1] - g_binRangeY[0]) break; } while (nearest == ushort(-1)); if (nearest != ushort(-1)) g_nodes[index].attribs.targetID = nearest; else if (IsValidTarget(g_nodes[index].attribs.targetID, index) == false) { // If our current target is invalid, and we weren't able to find a new one, we'll have to revert to N^2 for (uint i = 0; i < g_numNodes; i++) { if (IsValidTarget(i, index)) { uint dist = Distance(g_nodes[index].position, g_nodes[i].position); if (dist < minDist) { minDist = dist; nearest = i; } } } ASSERT(nearest != -1); g_nodes[index].attribs.targetID = nearest; } return S_OK; }
// Given a position in normalized 0..1 space, find the position's bin and // return its index into the slot buffer HRESULT Bin(float posx, float posy, int* bin) { int bucketX = uint(posx / g_binNWidth); int bucketY = uint(posy / g_binNHeight); return Bin(bucketX, bucketY, bin); }