zoukankan      html  css  js  c++  java
  • USACO section 1.4.2 The Clocks

    1. 这道题有好多种解法,看NOCOW,用枚举,DFS,BFS都能求解。我看到这个题的时候,连最基本的枚举怎么做都想不出来,差距呐。。。;

    2. 我挑选了解题报告中代码最短的读懂然后写出来了:

    /*
    ID: dollar4
    PROG: clocks
    LANG: C++
    */
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <algorithm>
    #include <cstring>
    #include <numeric>
    #include <climits>
    
    using namespace std;
    #define FOR(x) for (c[x] = 0; c[x] <= 3; c[x]++)
    int main()
    {
        ofstream fout ("clocks.out");
        ifstream fin ("clocks.in");
        int i, c[10], a[10], temp, s[10], rst[10], cnt, mincnt = INT_MAX;
        for (i = 0; i < 9; i++)
        {
            fin >> temp;
            a[i] = temp / 3 % 4;
        }
        FOR(1) FOR(2) FOR(3) FOR(4) FOR(5) FOR(6) FOR(7) FOR(8) FOR(9)
        {
            s[0] = (a[0] + c[1] + c[2] + c[4]) % 4;
            s[1] = (a[1] + c[1] + c[2] + c[3] + c[5]) % 4;
            s[2] = (a[2] + c[2] + c[3] + c[6]) % 4;
            s[3] = (a[3] + c[1] + c[4] + c[5] + c[7]) % 4;
            s[4] = (a[4] + c[1] + c[3] + c[5] + c[7] + c[9]) % 4;
            s[5] = (a[5] + c[3] + c[5] + c[6] + c[9]) % 4;
            s[6] = (a[6] + c[4] + c[7] + c[8]) % 4;
            s[7] = (a[7] + c[5] + c[7] + c[8] + c[9]) % 4;
            s[8] = (a[8] + c[6] + c[8] + c[9]) % 4;
            if (accumulate(s, s + 9, 0))
                continue;
            cnt = accumulate(c + 1, c + 10, 0);
            if (cnt < mincnt)
            {
                mincnt = cnt;
                copy(c + 1, c + 10, rst);
            }
    
        }
        for (i = 0; i < 9; i++)
            {
                while (rst[i]--)
                {
                    fout << i + 1;
                    if (--cnt)
                        fout << ' ';
                    else fout << endl;
                }
            }
        return 0;
    }
    

    3. 官方参考代码:

    Notice that the order in which we apply moves is irrelevant, and that applying a move four times is the same as applying it not at all.

    Thus there are only 49 = 262144 move sequences that need to be tried, so we might as well just try them all.

    We don't generate them shortest first, but looking at sequences of the same length, we generate the lesser ones before the greater ones, so we only need to keep track of the shortest working sequence we've found.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>
    #include <ctype.h>
    
    #define INF 60000	/* bigger than longest possible path */
    
    char *movestr[] = { "abde", "abc", "bcef", "adg", "bdefh", "cfi", "degh",
                        "ghi", "efhi" };
    
    int movedist[9][9];
    int clock[9];
    
    int bestmove[9];
    int nbestmove;
    
    /* translate move strings into array "movedist" of which clocks change on each move */
    void
    mkmove(void)
    {
        int i;
        char *p;
    
        for(i=0; i<9; i++)
    	for(p=movestr[i]; *p; p++)
    	    movedist[i][*p-'a'] = 3;
    }
    
    /* apply some number of each move from k to 9 */
    /* move contains the number of times each move is applied */
    void
    solve(int *move, int k)
    {
        int i, j, n, rep;
    
        if(k == 9) {
    	for(j=0; j<9; j++)
    	    if(clock[j]%12 != 0)
    		return;
    
    	/* we have a successful sequence of moves */
    	n = 0;
    	for(j=0; j<9; j++)
    	    n += move[j];
    
    	if(nbestmove == 0 || n < nbestmove) {
    	    nbestmove = n;
    	    for(j=0; j<9; j++)
    		bestmove[j] = move[j];
    	}
    	return;
        }
    
        /*
         * the for loop counts down so we
         * generate smaller numbers first by
         * trying more of small numbered
         * moves before we try less of them.
         */
        for(rep=3; rep>=0; rep--) {
    	/* apply move k rep times */
    	for(i=0; i<rep; i++)
    	    for(j=0; j<9; j++)
    		clock[j] += movedist[k][j];
    	move[k] = rep;
    
    	solve(move, k+1);
    
    	/* undo move */
    	for(i=0; i<rep; i++)
    	    for(j=0; j<9; j++)
    		clock[j] -= movedist[k][j];
        }
    }
    
    void
    main(void)
    {
        FILE *fin, *fout;
        int i, j, move[9];
        char *sep;
    
        fin = fopen("clocks.in", "r");
        fout = fopen("clocks.out", "w");
        assert(fin != NULL && fout != NULL);
    
        mkmove();
    
        for(i=0; i<9; i++)
    	fscanf(fin, "%d", &clock[i]);
    
        solve(move, 0);
    
        sep = "";
        for(i=0; i<9; i++) {
    	for(j=0; j<bestmove[i]; j++) {
    	    fprintf(fout, "%s%d", sep, i+1);
    	    sep = " ";
    	}
        }
        fprintf(fout, "\n");
    
        exit(0);
    }

    Lucian Boca submitted a constant time solution

    You can precalculate a matrix a as following:

    a[i][0],a[i][1],....,a[i][8] is the number of moves '1','2','3',...'9' necessarly to move ONLY clock i (where 0 < i <= 8 - there are 9 clocks: 0=A, 1=B, ... 8=I) 90 degrees clockwise. So, you have the matrix:

    int a[9][9]= { {3,3,3,3,3,2,3,2,0},
                   {2,3,2,3,2,3,1,0,1},
                   {3,3,3,2,3,3,0,2,3},
                   {2,3,1,3,2,0,2,3,1},
                   {2,3,2,3,1,3,2,3,2},
                   {1,3,2,0,2,3,1,3,2},
                   {3,2,0,3,3,2,3,3,3},
                   {1,0,1,3,2,3,2,3,2},
                   {0,2,3,2,3,3,3,3,3} };
    

    That means: to move ONLY the clock 0 (clock A) 90 degrees clockwise you have to do {3,3,3,3,3,2,3,2,0}, 3 moves of type 1, three moves of type 2, ..., 2 moves of type 8, 0 moves of type 9, etc.

    To move ONLY the clock 8 (clock I), you have to do the moves {0,2,3,2,3,3,3,3,3}: 0 moves of type 1, 2 moves of type 2... 3 moves of type 9....

    That's it! You count in a vector v[9] how many moves of each type you have to do, and the results will be modulo 4 (%4 - 5 moves of any type have the same effect 1 move has). The source code:

    #include <stdio.h>
    
    int a[9][9]= { {3,3,3,3,3,2,3,2,0},
                   {2,3,2,3,2,3,1,0,1},
                   {3,3,3,2,3,3,0,2,3},
                   {2,3,1,3,2,0,2,3,1},
                   {2,3,2,3,1,3,2,3,2},
                   {1,3,2,0,2,3,1,3,2},
                   {3,2,0,3,3,2,3,3,3},
                   {1,0,1,3,2,3,2,3,2},
                   {0,2,3,2,3,3,3,3,3} };
    int v[9];
    
    int main() {
        int i,j,k;
        freopen("clocks.in","r",stdin);
        for (i=0; i<9; i++) {
            scanf("%d",&k);
            for(j=0; j<9; j++)
                 v[j]=(v[j]+(4-k/3)*a[i][j])%4;
        }
        fclose(stdin);
    
        k=0;
        freopen("clocks.out","w",stdout);
        for (i=0; i<9; i++)
            for (j=0; j<v[i]; j++)
                if (!k) { printf("%d",i+1); k=1; }
                else    printf(" %d",i+1);
        printf("\n");
        fclose(stdout);
        return 0;
    }

    Here's a different approach from Sopot Cela -- no loops, constant time. It is, however, extraordinarily intricate: getting such a program correct in a contest environment could be extremely challenging:

    program clocks;
    const
      INV : array[3..12] of byte =(1, 0, 0, 2, 0, 0, 3, 0, 0, 0);
    
    var inp, out: text;
        a, b, c, d, e, f, g, h, i: integer;
        ax, bx, cx, dx, ex, fx, gx, hx, ix,l: integer;
        t,an: array[1..9] of integer;
    begin
        assign (inp, 'clocks.in'); reset (inp);
        readln(inp, ax, bx, cx);
        readln(inp, dx, ex, fx);
        readln(inp, gx, hx, ix);
        a:=inv[ax]; b:=inv[bx]; c:=inv[cx]; d:=inv[dx];
        e:=inv[ex]; f:=inv[fx]; g:=inv[gx]; h:=inv[hx];
        i:=inv[ix];
        t[1] := (8+a+2*b+c+2*d+2*e-f+g-h) mod 4;
        t[2] := (a+b+c+d+e+f+2*g+    2*i) mod 4;
        t[3] := (8+  a+2*b+  c  -d+2*e+2*f      -h+  i) mod 4;
        t[4] := (    a+  b+2*c+  d+  e+      g+  h+2*i) mod 4;
        t[5] := (4+  a+2*b+  c+2*d  -e+2*f+  g+2*h+  i) mod 4;
        t[6] := (  2*a+  b+  c+      e+  f+2*g+  h+  i) mod 4;
        t[7] := (8+  a  -b+    2*d+2*e  -f+  g+2*h+  i) mod 4;
        t[8] := (  2*a+    2*c+  d+  e+  f+  g+  h+  i) mod 4;
        t[9] := (8      -b+  c  -d+2*e+2*f+  g+2*h+  i) mod 4;
        assign(out, 'clocks.out'); rewrite(out);
        for a := 1 to 9 do
    	for b := 1 to t[a] do Begin
    	    inc(l);
    	    an[l]:=a;
    	end;
        for a:=1 to l-1 do
    	write(out,an[a],' ');
        write(out,an[l]);
        writeln(out); close(out)
    end.


  • 相关阅读:
    Docker windows下安装,入门及注意事项,并搭建包含Nodejs的webapp
    360浏览器table中的td为空时td边框不显示的解决方法
    关于发布webservice提示The test form is only available for requests from the local machine
    CRM相关SQl手记
    页面右下角弹出的消息提示框
    MS CRM2011 js常用总结
    MVC razor 使用服务器控件
    常用正则表达式
    CRM 2011 常用对象
    人工智能AI-机器视觉CV-数据挖掘DM-机器学习ML-神经网络-[资料集合贴]
  • 原文地址:https://www.cnblogs.com/dollarzhaole/p/3188914.html
Copyright © 2011-2022 走看看