USACO 3.3.3 Camelot

来源:互联网 发布:武汉java培训班有哪些 编辑:程序博客网 时间:2024/06/10 19:05

这是传说中的镇站神题么.. orz了


前前后后大概写了30k的代码,调了10+h才过...如果一开始就想清楚,只要调好2个typo,几个特判就好了,不用2个小时,所以写之前一定要想清楚细节...

首先用个四维数组保存任意点到任意点的距离,然后穷举集结点计算普通的骑士距离和,同时找出最短的先去载王再到集结点的距离。

一个优化是假设王自己的移动范围只有+-2.

同时要注意没有骑士和有骑士,但是格子数太小不能跳的情况。

代码如下:

#define TASK  "camelot"//#define SUBMIT//#define LOCAL#include <queue>#include <algorithm>#include <iostream>using namespace std;const int kx[] = {2,1,-1,-2,-2,-1,1,2};//knight jumpconst int ky[] = {1,2,2,1,-1,-2,-2,-1};const int maxn = 33;const int inf = 1234567;struct point {    int x, y, s;    point(int _x=0, int _y=0, int _s=0) {        x=_x, y=_y, s=_s;    }};point saber, k[maxn * maxn];bool inline isValid(point& p);void input();void init();int rr, cc; // rows , colsint cnt = 0; // cnt of knightsint ta[maxn][maxn][maxn][maxn]; //table for precalculate distpoint get[maxn*maxn]; //point to get saber onint nget = 0;void bfs();void solve();int main(){#ifdef LOCAL     freopen(TASK ".in","r",stdin);  #endif#ifdef SUBMIT    freopen(TASK ".out","w",stdout);#endif    input();    init();    //special judge    if (0 == cnt)  {        cout<<0<<endl;    }    else if (rr <3 && cc < 3) {        cout<<1<<endl;    }    else    {        bfs();        solve();    }    return 0;}void input() {    cin>>rr>>cc;    char a; int b;    cin>>a>>b;    saber.x = a - 'A' + 1; saber.y = b;    saber.s = 0;    k[0] = saber;    while(cin>>a>>b) {        k[++cnt].x = a - 'A' + 1;        k[cnt].y = b;    }}bool inline isValid(point& p) {    return p.x >0 && p.x <= cc && p.y>=1 && p.y<=rr;}void init() {    for (int i=1; i<=rr; i++) {        for (int j=1; j<=cc; j++) {            for (int k=1; k<=rr; k++) {                for (int l=1; l<=cc; l++)                {                    ta[i][j][k][l] = inf;                }            }        }    }    int sax = max(1, saber.x-2);    int say = max(1, saber.y - 2);    int tax = min(cc, saber.x+2);    int tay = min(rr, saber.y + 2);    for (int i=sax; i<=tax; i++) {        for (int j=say; j<=tay; j++) {            get[++nget] = point(i, j);        }    }}void solve() {    int ret = inf, xpick, ypick, xga, yga;    xga = yga = xpick = ypick = -1;  // for debug     for (int i=1; i<=nget; i++) {        int foo = max(abs(saber.y - get[i].y), abs(saber.x - get[i].x));        for (int sy=1; sy<=rr; sy++) {            for (int sx=1; sx<=cc; sx++) {                int ans = 0, bestfs = inf;                for (int id=1; id<=cnt; id++) {                    ans += ta[k[id].y][k[id].x][sy][sx];                    // calcucate the extra expense to get saber first and go to gather point than direct                    int tmpfs = ta[k[id].y][k[id].x][get[i].y][get[i].x]                        + foo + ta[get[i].y][get[i].x][sy][sx]                        - ta[k[id].y][k[id].x][sy][sx];                    if (tmpfs < bestfs) {                        bestfs = tmpfs;                        xpick = get[i].x; ypick = get[i].y;                    }                }                if (ans + bestfs < ret) {                    ret = ans + bestfs;                    xga = sx, yga = sy;                }            }        }    }    cout<<ret<<endl;}void bfs() {    for (int sy=1; sy<=rr; sy++) {        for (int sx=1; sx<=cc; sx++) {            ta[sy][sx][sy][sx] = 0;            point u = point(sx, sy); u.s=0;            queue<point> q;            q.push(u);            int vis[maxn][maxn]; memset(vis, 0, sizeof(vis));            vis[u.y][u.x] = 1;            while(q.size()) {                point cur = q.front(); q.pop();                for (int i=0; i<8; i++) {                    point tmp;                    tmp.y = cur.y + ky[i];                    tmp.x = cur.x + kx[i];                    tmp.s = cur.s + 1;                    if (isValid(tmp) && vis[tmp.y][tmp.x] == 0) {                        vis[tmp.y][tmp.x] = 1;                        ta[sy][sx][tmp.y][tmp.x] = tmp.s;                        q.push(tmp);                    }                }            }        }    }}


第十组数据usaco的机器居然比我的air跑得快1/3... 是机器升级了还是1.65G实在太渣..

Compiling...Compile: OKExecuting...   Test 1: TEST OK [0.000 secs, 8036 KB]   Test 2: TEST OK [0.011 secs, 8168 KB]   Test 3: TEST OK [0.011 secs, 8168 KB]   Test 4: TEST OK [0.032 secs, 8168 KB]   Test 5: TEST OK [0.119 secs, 8168 KB]   Test 6: TEST OK [0.130 secs, 8168 KB]   Test 7: TEST OK [0.000 secs, 8168 KB]   Test 8: TEST OK [0.011 secs, 8168 KB]   Test 9: TEST OK [0.076 secs, 8168 KB]   Test 10: TEST OK [0.292 secs, 8168 KB]   Test 11: TEST OK [0.000 secs, 8168 KB]   Test 12: TEST OK [0.011 secs, 8168 KB]   Test 13: TEST OK [0.011 secs, 8168 KB]   Test 14: TEST OK [0.011 secs, 8168 KB]   Test 15: TEST OK [0.011 secs, 8168 KB]   Test 16: TEST OK [0.011 secs, 8168 KB]   Test 17: TEST OK [0.032 secs, 8168 KB]   Test 18: TEST OK [0.000 secs, 8036 KB]   Test 19: TEST OK [0.000 secs, 8168 KB]   Test 20: TEST OK [0.000 secs, 8168 KB]All tests OK.Your program ('camelot') produced all correct answers!  This is yoursubmission #4 for this problem.  Congratulations!



原创粉丝点击