JMK no matter what

SRM449 practice

A simple geometry 250, counting 550 and quite tricky 950. I thought I didn't have a chance writing both 550 and 950 in time, and wasted some time looking and thinking about both problems. I finally went for 550 - that proved to be easier than I thought. So the score is not great... but anyway.

Ah, and the source code for this match was committed with revision 1000 of my personal SVN repository.

250 MaxTriangles

lang:cpp
#include<iostream>
#include<cstring>
#include<algorithm>
#include<sstream>
#include<string>
#include<vector>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<fstream>
#include<cassert>
#include<numeric>
#include<set>
#include<map>
#include<queue>
#include<list>
#include<deque>
using namespace std;

#define FOR(i,a,b) for(int i = (a); i < (b); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORE(it,x) for(typeof(x.begin()) it=x.begin();it!=x.end();++it)
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define CLEAR(x,with) memset(x,with,sizeof(x))
#define sz size()
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef long long ll;

const int M = 44722;
struct MaxTriangle 
{
    set<int> sqs;
    VI possibleX(int R2)
    {
        VI ret;
        REP(x,M) 
        {
            int x2 = x*x, y2 = R2-x2;
            if(sqs.count(y2)) ret.pb(x);
        }
        return ret;
    }
    double getY(double dist, double x)
    {
        return sqrt(dist - x*x); 
    }
    double calculateArea( int A, int B ) 
    {
        REP(i,M) sqs.insert(i*i);
        vector<int> xA = possibleX(A);
        vector<int> xB = possibleX(B);
        double ret = -1;
        REP(i,xA.sz) REP(j,xB.sz)
        {
            ret = max(ret, (xA[i] * getY(B, xB[j]) + getY(A, xA[i]) * xB[j])/2);
        }
        return ret;
    }
};

500 HexagonBattlefield

Apart from the fact that it uses hexagonal grids, 550 is just plain standard exponential DP.

lang:cpp
#include<iostream>
#include<cstring>
#include<algorithm>
#include<sstream>
#include<string>
#include<vector>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<fstream>
#include<cassert>
#include<numeric>
#include<set>
#include<map>
#include<queue>
#include<list>
#include<deque>
using namespace std;

#define FOR(i,a,b) for(int i = (a); i < (b); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORE(it,x) for(typeof(x.begin()) it=x.begin();it!=x.end();++it)
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define CLEAR(x,with) memset(x,with,sizeof(x))
#define sz size()
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef long long ll;

typedef pair<int,int> point;
int cache[17][(1<<16)+10];
const int dx[6] = { 1, 0, -1 };
const int dy[6] = { 0, -1, -1 };
const int BIAS = 8;
const int M = 2000000011;
struct HexagonalBattlefield 
{
    vector<point> p;
    int bufA[17], bufB[17];
    int *minRow, *maxRow;
    VI next[200];
    map<point,int> index;    
    VI taken;
    int N;

    int go(int y, int x, int loc)
    {
        if(y < -(N-1)) return 1;
        if(x > maxRow[y]) return go(y-1, minRow[y-1], loc);
        int mask = -1;
        if(x == minRow[y])
        {
            mask = 0;
            int rw = maxRow[y]+1-minRow[y];
            REP(i,rw)
                mask = mask * 2 + taken[i+loc];
            if(cache[y+BIAS][mask] != -1) return cache[y+BIAS][mask];
        }
        ll ret = 0;
        if(taken[loc]) 
            ret = go(y, x+1, loc+1);
        else
        {
            REP(i,next[loc].sz)
            {
                int other = next[loc][i];
                if(taken[other]) continue;
                taken[other] = 1;
                (ret += go(y, x+1, loc+1)) %= M;
                taken[other] = 0;
            }
        }
        if(mask != -1) cache[y+BIAS][mask] = ret;
        return ret;
    }

    int countArrangements( vector <int> X, vector <int> Y, int N_ ) 
    {
        N = N_;
        minRow = bufA + BIAS;
        maxRow = bufB + BIAS;
        // gen graph
        for(int y = N-1; y >= -(N-1); --y)
        {
            int rowWidth = N+N-1 - abs(y);
            minRow[y] = max(-(N-1)+y, -(N-1));
            maxRow[y] = minRow[y] + rowWidth - 1;
            printf("minRow[%d] = %d, maxRow[%d] = %d\n", y, minRow[y], y, maxRow[y]);
            FOR(x,minRow[y],maxRow[y]+1)
            {
                p.push_back(point(y, x));
                index[p.back()] = p.sz-1;
            }
        }
        REP(i,p.sz) 
        {
            //printf("point #%d (%d,%d)\n", i, p[i].first, p[i].second);
            REP(k,3)
            {
                point q = point(p[i].first + dy[k], p[i].second + dx[k]);
                if(index.count(q))
                {
                    next[i].pb(index[q]);
                    //printf("\tnext %d (%d,%d)\n", index[q], q.first, q.second);
                }
            }
        }
        CLEAR(cache,-1);
        taken.assign(p.sz, 0);
        REP(i,X.sz)
        {
            point q(Y[i], X[i]);
            assert(index.count(q));
            taken[index[q]] = 1;
        }
        return go(N-1, minRow[N-1], 0);
    }
};
2009-11-04 08:41:35 | JM | /logs/topcoder/ | 0 개의 댓글들

댓글 남기기