USACO Section 1.4 Mother's Milk

题目原文

Mother's Milk

Farmer John has three milking buckets of capacity A, B, and C liters. Each of the numbers A, B, and C is an integer from 1 through 20, inclusive. Initially, buckets A and B are empty while bucket C is full of milk. Sometimes, FJ pours milk from one bucket to another until the second bucket is filled or the first bucket is empty. Once begun, a pour must be completed, of course. Being thrifty, no milk may be tossed out.

Write a program to help FJ determine what amounts of milk he can leave in bucket C when he begins with three buckets as above, pours milk among the buckets for a while, and then notes that bucket A is empty.

PROGRAM NAME: milk3

INPUT FORMAT

A single line with the three integers A, B, and C.

SAMPLE INPUT (file milk3.in)

8 9 10

OUTPUT FORMAT

A single line with a sorted list of all the possible amounts of milk that can be in bucket C when bucket A is empty.

SAMPLE OUTPUT (file milk3.out)

1 2 8 9 10

SAMPLE INPUT (file milk3.in)

2 5 10

SAMPLE OUTPUT (file milk3.out)

5 6 7 8 9 10

分析

根据题目的意思我们知道,在每一步倒牛奶的过程中都存在6种情况,C-A,C-B,A-B,A-C,B-A,B-C,求最后的解那就变成了一个搜索问题,由于题目中把数字限制在20以内,所以实际的搜索次数不超过20*20=400次。可以使用深度优先或者广度优先搜索结果,本文使用广度优先搜索。

提交代码

/*
ID: 
PROG: milk3
LANG: C++
*/


#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;

struct buckets_state
{
	vector<int> capacity;
	vector<int> milk;

	buckets_state()
	{
		capacity.resize(3);
		milk.resize(3);
	}
};


buckets_state pour(const buckets_state& cur,const int src, const int des)
{
	buckets_state out;
	out.capacity = cur.capacity;
	out.milk = cur.milk;
	out.milk[src] = max(cur.milk[src]-cur.capacity[des]+cur.milk[des],0);
	out.milk[des] = min(cur.capacity[des],cur.milk[des]+cur.milk[src]);

	return out;
}

void search(vector<vector<bool> > &check,const buckets_state &ini_state,vector<int> &ans)
{
	if(check[ini_state.milk[0]][ini_state.milk[1]])
		return;
	check[ini_state.milk[0]][ini_state.milk[1]] = true;
	
	if(ini_state.milk[0] == 0)
		ans.push_back(ini_state.milk[2]);

	if(ini_state.milk[0] != 0)
	{
		search(check,pour(ini_state,0,1),ans);
		search(check,pour(ini_state,0,2),ans);
	}
	if(ini_state.milk[1] != 0)
	{
		search(check,pour(ini_state,1,0),ans);
		search(check,pour(ini_state,1,2),ans);
	}
	if(ini_state.milk[2] != 0)
	{
		search(check,pour(ini_state,2,0),ans);
		search(check,pour(ini_state,2,1),ans);
	}

}



int main()
{
	ifstream fin("milk3.in");
	ofstream fout("milk3.out");

	buckets_state ini_state;
	fin >> ini_state.capacity[0] >> ini_state.capacity[1] >> ini_state.capacity[2];
	ini_state.milk[2] = ini_state.capacity[2];

	vector<vector<bool> > checklst(21);
	for (int i=0;i!=21;i++)
		checklst[i].resize(21);
	vector<int> ans;
	search(checklst,ini_state,ans);

	sort(ans.begin(),ans.end());
	
	for (int i=0;i!=ans.size();i++)
	{
		fout << ans[i];
		if(i!=ans.size()-1)
			fout << " ";
		else
			fout << endl;
	}
	return 0;
}

提交结果

TASK: milk3
LANG: C++

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.011 secs, 3508 KB]
   Test 2: TEST OK [0.011 secs, 3508 KB]
   Test 3: TEST OK [0.011 secs, 3508 KB]
   Test 4: TEST OK [0.008 secs, 3508 KB]
   Test 5: TEST OK [0.008 secs, 3508 KB]
   Test 6: TEST OK [0.005 secs, 3508 KB]
   Test 7: TEST OK [0.005 secs, 3508 KB]
   Test 8: TEST OK [0.003 secs, 3508 KB]
   Test 9: TEST OK [0.000 secs, 3508 KB]
   Test 10: TEST OK [0.003 secs, 3508 KB]

官方参考答案

#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);
}

THE END

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值