zoukankan      html  css  js  c++  java
  • USACO section 1.4.4 Mother's Milk

    1. 用dfs,[A][B][C]为三个状态,且只有6个操作,a倒b,a倒c,b倒a,b倒c,c倒a,c倒b。知道用深搜了,但是还是不知道怎么写,看了别人的代码,才会写dfs()这个函数了。其实确定深搜了之后,写这个函数的时候,不需要考虑递归是怎么进行的,只需要考虑这次和下一次的操作过程即可。

    2. 以下是代码:

    /*
    ID: dollar4
    PROG: milk3
    LANG: C++
    */
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <algorithm>
    #include <cstring>
    
    using namespace std;
    int a, b, c, p = 0, isin[20];
    int vis[21][21][21];
    int ans[21];
    bool cmp(int a, int b)
    {
        return a < b;
    }
    void dfs(int aa, int bb, int cc)
    {
        if (vis[aa][bb][cc])
            return;
        vis[aa][bb][cc] = 1;
        if (aa == 0 && !isin[cc])
        {
    
            isin[cc] = 1;
            ans[p++] = cc;
        }
        if (aa >= b - bb)//a->b
            dfs(aa - b + bb, b, cc);
        else dfs(0, bb + aa, cc);
        if (bb >= a - aa)// b->a
            dfs(a, bb - a + aa, cc);
        else dfs(aa + bb, 0, cc);
        if (cc >= b - bb) // c->b
            dfs(aa, b, cc - b + bb);
        else dfs(aa, bb + cc, 0);
        if (cc >= a - aa) // c->a
            dfs(a, bb, cc - a + aa);
        else dfs(aa + cc, bb, 0);
        if (aa >= c - cc) // a->c
            dfs(aa - c + cc, bb, c);
        else dfs(0, bb, cc + aa);
        if (bb >= c - cc) // b->c
            dfs(aa, bb - c + cc, c);
        else dfs(aa, 0, cc + bb);
        return;
    }
    int main()
    {
        ofstream fout ("milk3.out");
        ifstream fin ("milk3.in");
        memset(vis, 0, sizeof(vis));
        memset(isin, 0, sizeof(isin));
        memset(ans, 0, sizeof(ans));
        fin >> a >> b >> c;
        dfs(0, 0, c);
        sort(ans, ans + p, cmp);
        int cnt = p - 1;
        for (int i = 0; i < p; i++)
        {
            fout << ans[i];
            if (cnt--)
                fout << ' ';
            else fout << endl;
        }
        return 0;
    }
    

    3. 官方参考代码

    We use a simple depth-first search to find all the possible states for the three buckets, pruning the search by not researching from states we've seen before.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>
    #include <ctype.h>
    
    #define MAX 20
    
    typedef struct State	State;
    struct State {
        int a[3];
    };
    
    int seen[MAX+1][MAX+1][MAX+1];
    int canget[MAX+1];
    
    State
    state(int a, int b, int c)
    {
        State s;
    
        s.a[0] = a;
        s.a[1] = b;
        s.a[2] = c;
        return s;
    }
    
    int cap[3];
    
    /* pour from bucket "from" to bucket "to" */
    State
    pour(State s, int from, int to)
    {
        int amt;
    
        amt = s.a[from];
        if(s.a[to]+amt > cap[to])
    	amt = cap[to] - s.a[to];
    
        s.a[from] -= amt;
        s.a[to] += amt;
        return s;
    }
    
    void
    search(State s)
    {
        int i, j;
    
        if(seen[s.a[0]][s.a[1]][s.a[2]])
    	return;
    
        seen[s.a[0]][s.a[1]][s.a[2]] = 1;
    
        if(s.a[0] == 0)	/* bucket A empty */
    	canget[s.a[2]] = 1;
    
        for(i=0; i<3; i++)
        for(j=0; j<3; j++)
    	search(pour(s, i, j));	
    }
    
    void
    main(void)
    {
        int i;
        FILE *fin, *fout;
        char *sep;
    
        fin = fopen("milk3.in", "r");
        fout = fopen("milk3.out", "w");
        assert(fin != NULL && fout != NULL);
    
        fscanf(fin, "%d %d %d", &cap[0], &cap[1], &cap[2]);
    
        search(state(0, 0, cap[2]));
    
        sep = "";
        for(i=0; i<=cap[2]; i++) {
    	if(canget[i]) {
    	    fprintf(fout, "%s%d", sep, i);
    	    sep = " ";
    	}
        }
        fprintf(fout, "\n");
    
        exit(0);
    }

    Ran Pang from Canada sends this non-recursive DP solution:

    #include<stdio.h>
    
    int m[21][21][21];
    int poss[21];
    int A, B, C;
    
    int main(void) {
        int i,j,k;
        int flag;
        FILE* in=fopen("milk3.in","r");
        fscanf(in, "%d %d %d",&A, &B, &C);
        fclose(in);
        for(i=0;i<21;i++)
            for(j=0;j<21;j++)
                for(k=0;k<21;k++)
                    m[i][j][k]=0;
        for(i=0;i<21;i++)
            poss[i]=0;
        m[0][0][C]=1;
    
        for(flag=1;flag;) {
            flag=0;
            for(i=0;i<=A;i++)
                for(j=0;j<=B;j++)
                    for(k=0;k<=C;k++) {
                        if(m[i][j][k]) {
                    	if(i==0) poss[k]=1;
    		        if(i) {
    	                    if(j<B) {
                                    if(B-j>=i) {
                                	    if( m[0][j+i][k]==0) {
                                            m[0][j+i][k]=1;
                                    	flag=1;
                                	    }
                                    } else {
                                	    if( m[i-(B-j)][B][k] == 0) {
                                            m[i-(B-j)][B][k] =1;
                                            flag=1;
                                        }
                                    }
                                }
                                if(k<C) {
                                    if(C-k>=i) {
                                        if( m[0][j][k+i]==0) {
                                            m[0][j][k+i]=1;
                                            flag=1;
                                        }
                                    }
                                    else {
                                        if( m[i-(C-k)][j][C] == 0) {
                                            m[i-(C-k)][j][C] =1;
                                            flag=1;
                                        }
                                    }
                                }
                            }
                            if(j) {
                                if(i<A) {
                                    if(A-i>=j) {
                                        if( m[i+j][0][k]==0) {
                                            m[i+j][0][k]=1;
                                            flag=1;
                                        }
                                    } else {
                                        if( m[A][j-(A-i)][k] == 0) {
                                            m[A][j-(A-i)][k] =1;
                                            flag=1;
                                        }
                                    }
                                }
                                if(k<C) {
                                    if(C-k>=j) {
                                        if( m[i][0][k+j]==0) {
                                            m[i][0][k+j]=1;
                                            flag=1;
                                        }
                                    } else {
                                        if( m[i][j-(C-k)][C] == 0) {
                                            m[i][j-(C-k)][C] =1;
                                            flag=1;
                                        }
                                    }
                                }
                            }
                            if(k) {
                                if(i<A) {
                                    if(A-i>=k) {
                                        if( m[i+k][j][0]==0) {
                                            m[i+k][j][0]=1;
                                            flag=1;
                                        }
                                    } else {
                                        if( m[A][j][k-(A-i)] == 0) {
                                            m[A][j][k-(A-i)] =1;
                                            flag=1;
                                        }
                                    }
                                }
                                if(j<B) {
                                    if(B-j>=k) {
                                        if( m[i][j+k][0]==0) {
                                            m[i][j+k][0]=1;
                                            flag=1;
                                        }
                                    } else {
                                        if( m[i][B][k-(B-j)] == 0) {
                                            m[i][B][k-(B-j)] =1;
                                            flag=1;
                                        }
                                    }
                                }
                            }
                }                   
            }
        }
        {
            FILE* out=fopen("milk3.out", "w");
            for(i=0;i<21;i++) {
                if(poss[i]) {
                    fprintf(out,"%d",i);
                    i++;
                    break;
                }
            }
            for(;i<21;i++) {
                if(poss[i]) {
                    fprintf(out, " %d", i);
                }
            }
            fprintf(out,"\n");
        }
        return 0;
    }

    Daniel Jasper from Germany writes:

    Both other solutions (recursive and non-recursive) use a 3D-array to store the states, so that the memory usage is O(N3). However a 2D Array and O(N2) would be enough since a state is uniquely defined by the amount of milk in bucket B and C. The amount of milk in bucket A is size-of-C minus amount-in-C minus amount-in-B. This solution works with it, and is a little bit shorter (though not more elegant):

    #include <stdio.h>
    int A, B, C;
    int CB[21][21]; // All states
    
    void readFile() {
        FILE *f;
        f = fopen("milk3.in", "r");
        fscanf(f, "%d%d%d", &A, &B, &C);
        fclose(f);
    }
    
    void writeFile() {
        FILE *f; int i;
        f = fopen("milk3.out", "w");
        for(i = 0; i <= C; i++) {
            if(CB[i][C - i] == 1) {
                if((i != C-B) && (i != 0)) fprintf(f, " ");
                fprintf(f, "%d", i);
            }
        }
        fprintf(f, "\n");
        fclose(f);
    }
    
    // do brute-force search, c/b: current state
    void search(int c, int b) {
        int a;
        if(CB[c][b] == 1) return; // already searched
        CB[c][b] = 1;
        a = C-b-c; // calc amount in A
        // do all moves:
        // c->b
        if(B < c+b) search(c - (B - b), B);
        else search(0, c + b);
        // b->c
        if(C < c+b) search(C, b - (C - c));
        else search(c + b, 0);
        // c->a
        if(A < c+a) search(c - (A - a), b);
        else search(0, b);
        // a->c
        if(C < c+a) search(C, b);
        else search(c + a, b);
        // b->a
        if(A < b+a) search(c, b - (A - a));
        else search(c, 0);
        // a->b
        if(B < b+a) search(c, B);
        else search(c, b + a);
       }
       
    int main () {
        readFile();
        search(C, 0);
        writeFile();
        return 0;
    }


  • 相关阅读:
    vue-cli 安装一直失败
    如果不存在公缀,返回空字符串
    .sh文件格式问题dos转linux或unix
    Kettle串联多个Spark任务
    云效自动化部署+部署包备份
    云效分支管理
    云效IDE综合插件Alibaba Cloud Toolkit
    流水线自动化部署-中转部署-目标机器不联网情况下应用
    云效流水线自动化部署
    云效流水线自动发布到Maven仓
  • 原文地址:https://www.cnblogs.com/dollarzhaole/p/3188912.html
Copyright © 2011-2022 走看看