2个空水壶,容积分别为3升和7升,如何只用这2个水壶从池塘里取得5升的水 -- 之程序实现
来源:互联网 发布:ios windows 编辑:程序博客网 时间:2024/04/28 23:58
又一次切换工作,在工作交接期间,有些时间来访问CSDN了
当时闲的无事,把下面的一个高校俱乐部的问题用程序来实现了下,暂时发现有3种方案:
1. 穷举法,不断的尝试,找到符合要求的方案
2. 使用迪斯特拉算法,找到最优的算法及操作方案
3. 类似能量守恒定理,可以解释得到如下不定方程:3x+7y=5; #如果此方程通过数学定理可以解释,那么一切的类似问题都非常简单了...
有两年没有写代码了,还有很多可以优化的地方
马上要忙起来了,我这边先这样, 如果有时间,再来处理吧...
假设有一个池塘,里面有无穷多的水。现有2个空水壶,容积分别为3升和7升。问题是如何只用这2个水壶从池塘里取得5升的水。
/****************************************************************************************
Function: Two bottles, one bottle container is 3L, another one is 7L;
There is enough water in the bucket, we should use that two bottles to get 5L water.
Comments:
1. Use status machine to get every valid operations
2. Use stack to save current water status and next operations.
3. We assume the operation steps less than MAX_OPERATION_STEPS
4. We assume that get the water from bucket should be less than MAX_IN_WATER
Ver0.11:
1. Try to search all of the ways to get the operation steps
Ver0.12:
1. How to get the min value? Dijekstr's Algorithm?
2. Dojkestra Algorithm passed.
3. Save the shortest path
Ver0.13:
1. We can use below expresion to get the operation steps:
CONTAINER_3L * x + CONTAINER_7L * y == CONTAINER_TARGET
2. Because we can think it like this:
a. There are two bottles, if we arrived the target, that's mean "CONTAINER_7L" bottle has CONTAINER_TARGET water
and we can OUTPUT all of the water in "CONTAINER_3L" bottle after we arrived the target.
INPUT - OUTPUT == CONTAINER_TARGET; SHIFT operation can't add/dicrease any water.
b. It can't be INPUT/OUT water not "mod" CONTAINER_3L or CONTAINER_7L;
We haven't other container, so every INPUT/OUTPUT should be used by CONTAINER_3L/7L;
If it input/out value is not mod "CONTAINER_3L/7L", it will be occurs from previous operation which from 3L/7L.
so INPUT-OUTPUT == CONTAINER_3L * x + CONTAINER_7L * y
Creater: work2free
*****************************************************************************************/
#include "iostream.h" //just used VC compiler.
//#define DIJKESTRA
#define INPUT_OUTPUT_MODE
#define CONTAINER_3L 3
#define CONTAINER_7L 7
#define MAX_STATUS (CONTAINER_3L + 1) * (CONTAINER_7L + 1)
#define CONTAINER_TARGET 5
#define MAX_OPERATION_STEPS ((MAX_STATUS) * (MAX_STATUS) + 1)
#define MAX_IN_WATER 200
//The operations should be only in these enum type.
typedef enum {
IN_3L,
OUT_3L,
SHIFT_3L_7L,
IN_7L,
OUT_7L,
SHIFT_7L_3L,
E_OPERATION_ERROR,
}E_Operation;
//current bottles contain how much water
typedef struct Node_Tag {
int value_3L;
int value_7L;
E_Operation operation;
int min_value; //
}Node_T;
static int s_status_operation_map [CONTAINER_3L + 1][CONTAINER_7L + 1][E_OPERATION_ERROR]; //(CONTAINER_3L + 1)*(CONTAINER_7L + 1) * E_OPERATION_ERROR
static Node_T s_statck_array[MAX_OPERATION_STEPS];
static unsigned int s_statck_index; //The value means there is how many node in the stack
static Node_T s_save_min_array[MAX_OPERATION_STEPS];
static unsigned int s_min_index; //The value means there is how many node in the stack
static int s_total_min = MAX_IN_WATER;
// return 1 means valid
int JudgeValidOperation (int value_3L, int value_7L, E_Operation operation)
{
if (value_3L > CONTAINER_3L || value_7L > CONTAINER_7L)
{
return -1;
}
switch (operation)
{
case IN_3L:
{
if (value_3L < CONTAINER_3L)
{
return 1;
}
return 0;
}
case OUT_3L:
{
if (value_3L != 0)
{
return 1;
}
return 0;
}
case SHIFT_3L_7L:
{
if (value_3L != 0 && value_7L < CONTAINER_7L)
{
return 1;
}
return 0;
}
case IN_7L:
{
if (value_7L < CONTAINER_7L)
{
return 1;
}
return 0;
}
case OUT_7L:
{
if (value_7L != 0)
{
return 1;
}
return 0;
}
case SHIFT_7L_3L:
{
if (value_7L != 0 && value_3L < CONTAINER_3L)
{
return 1;
}
return 0;
}
default:
return 0;
}
return 0;
}
int InitStatusOperationMap ()
{
int iloop_value_3L;
int iloop_value_7L;
E_Operation iloop_operation;
for (iloop_value_3L = 0; iloop_value_3L <= CONTAINER_3L; iloop_value_3L ++)
{
for (iloop_value_7L = 0; iloop_value_7L <= CONTAINER_7L; iloop_value_7L ++)
{
for (iloop_operation = 0; iloop_operation <= SHIFT_7L_3L; iloop_operation ++)
{
s_status_operation_map[iloop_value_3L][iloop_value_7L][iloop_operation] =
JudgeValidOperation (iloop_value_3L, iloop_value_7L, iloop_operation);
if (s_status_operation_map[iloop_value_3L][iloop_value_7L][iloop_operation] == -1)
{
printf ("InitStatusOperationMap ERROR: iloop_value_3L = %d, iloop_value_7L = %d, iloop_operation = %d\n", iloop_value_3L, iloop_value_7L, iloop_operation);
return -1;
}
}
}
}
}
int GetStackTotalWater ()
{
int iloop = 0;
int total_water = 0;
if (s_statck_index == 1) //only one
return (s_statck_array[iloop].value_3L + s_statck_array[iloop].value_7L);
//Check whether total IN water more than 15
for (iloop = 0; iloop < s_statck_index - 1; iloop ++)
{
//Water total value is large than min
if (s_statck_array[iloop].operation == IN_3L)
{
if (iloop == 0)
{
total_water += CONTAINER_3L;
}
else
{
total_water += (CONTAINER_3L - s_statck_array[iloop].value_3L);
}
}
else if (s_statck_array[iloop].operation == IN_7L)
{
if (iloop == 0)
{
total_water += CONTAINER_7L;
}
else
{
total_water += (CONTAINER_7L - s_statck_array[iloop].value_7L);
}
}
}
return total_water;
}
int OperateResult (Node_T current_node, Node_T *result_node_p)
{
if (result_node_p == 0)
{
return -1;
}
result_node_p->value_3L = current_node.value_3L;
result_node_p->value_7L = current_node.value_7L;
if (JudgeValidOperation (current_node.value_3L, current_node.value_7L, current_node.operation) == 1)
{
switch (current_node.operation)
{
case IN_3L:
{
if (result_node_p->value_3L != CONTAINER_3L)
{
result_node_p->value_3L = CONTAINER_3L;
return 1;
}
return 0;
}
case OUT_3L:
{
result_node_p->value_3L = 0;
return 1;
}
case SHIFT_3L_7L:
{
if (current_node.value_7L == CONTAINER_7L || result_node_p->value_3L == 0)
return 0;
if (current_node.value_3L + current_node.value_7L > CONTAINER_7L)
{
result_node_p->value_3L = current_node.value_3L + current_node.value_7L - CONTAINER_7L;
result_node_p->value_7L = CONTAINER_7L;
return 1;
}
else
{
result_node_p->value_7L = current_node.value_3L + current_node.value_7L;
result_node_p->value_3L = 0;
return 1;
}
}
case IN_7L:
{
if (result_node_p->value_7L != CONTAINER_7L)
{
result_node_p->value_7L = CONTAINER_7L;
return 1;
}
return 0;
}
case OUT_7L:
{
result_node_p->value_7L = 0;
return 1;
}
case SHIFT_7L_3L:
{
if (current_node.value_7L == 0 || result_node_p->value_3L == CONTAINER_3L)
return 0;
if (current_node.value_3L + current_node.value_7L > CONTAINER_3L)
{
result_node_p->value_7L = current_node.value_3L + current_node.value_7L - CONTAINER_3L;
result_node_p->value_3L = CONTAINER_3L;
return 1;
}
else
{
result_node_p->value_3L = current_node.value_3L + current_node.value_7L;
result_node_p->value_7L = 0;
return 1;
}
return 0;
}
default:
return 0;
}
}
else
{
return -1;
}
}
int JudgeTopNodeValid ()
{
int total_water = GetStackTotalWater ();
int iloop = 0;
Node_T result_node = {0, 0, IN_3L};
if (s_statck_index == 0)
return 0;
if (JudgeValidOperation (s_statck_array[s_statck_index - 1].value_3L,
s_statck_array[s_statck_index - 1].value_7L,
s_statck_array[s_statck_index - 1].operation) != 1)
return 0;
//Check whether the operation result is the same as previous node
if (!OperateResult (s_statck_array[s_statck_index - 1], &result_node)) //The operation is the same as previous one
return 0;
for (iloop = 0; iloop < s_statck_index - 1; iloop ++)
{
if (s_statck_array[iloop].value_3L == result_node.value_3L
&& s_statck_array[iloop].value_7L == result_node.value_7L)
return 0;
}
//We should find a way to get the latest water
//if (s_total_min < GetStackTotalWater ())
{
//return 0;
}
return 1;
}
#ifdef DIJKESTRA
#define MAX_VERTEX_NUM (MAX_STATUS)
#define ERROR_VERTEX (MAX_VERTEX_NUM + 2)
#define MAX_DISTANCE 1000000
//using namespace std;
//int s_num_vertex = MAX_STATUS; //vertex number
int s_arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
int s_shortest_distance[MAX_VERTEX_NUM]; //Save shortest length
int s_exist_path[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//path
int s_shortest_vertex_gather[MAX_VERTEX_NUM];//if s_shortest_vertex_gather[i] == 1, that's mean the vertex already in gather V.
int s_start_vertex = 0; //start vertex (0, 0)
int s_end_vertex = CONTAINER_TARGET; //end vertex (0, 5)
int s_path[ERROR_VERTEX][ERROR_VERTEX]; //from s_start_vertex to s_end_vertex, if there is path, save all of the passed vertex
//Only compute in water value
int GetOperationDistance (int value_3L, int value_7L, E_Operation operation)
{
int distance = 0;
if (value_3L > CONTAINER_3L || value_7L > CONTAINER_7L)
{
return -1;
}
switch (operation)
{
case IN_3L:
{
if (value_3L < CONTAINER_3L)
{
distance = CONTAINER_3L - value_3L;
}
return distance;
}
case IN_7L:
{
if (value_7L < CONTAINER_7L)
{
distance = CONTAINER_7L - value_7L;
}
return distance;
}
case OUT_3L:
case SHIFT_3L_7L:
case OUT_7L:
case SHIFT_7L_3L:
{
return 0;
}
default:
return 0;
}
return 0;
}
int InitDijkstraArcs ()
{
int iloop_from_index = 0; //from vertex
int iloop_to_index = 0; //to vertex
int from_value_3L = 0;
int from_value_7L = 0;
int to_index = 0;
int iloop_operation = 0;
for (iloop_from_index = 0; iloop_from_index <= MAX_STATUS; iloop_from_index ++)
{
//default: set the distance is max, self vertex exists path and distance is 0
for (iloop_to_index = 0; iloop_to_index <= MAX_STATUS; iloop_to_index ++)
{
s_arcs[iloop_from_index][iloop_to_index] = MAX_DISTANCE;
//self vertex: there is path and the distance is 0
if (iloop_to_index == iloop_from_index)
{
s_arcs[iloop_from_index][iloop_to_index] = 0;
}
}
//check:the operation has some path
for (iloop_operation = 0; iloop_operation < E_OPERATION_ERROR; iloop_operation ++)
{
Node_T from_vertex;
Node_T to_vertex;
int operate_result = 0;
from_value_3L = iloop_from_index/(CONTAINER_7L + 1);
from_value_7L = iloop_from_index%(CONTAINER_7L + 1);
from_vertex.value_3L = from_value_3L;
from_vertex.value_7L = from_value_7L;
from_vertex.operation = iloop_operation;
operate_result = OperateResult (from_vertex, &to_vertex);
if (operate_result == 1) //there is path
{
to_index = to_vertex.value_3L * (CONTAINER_7L + 1) + to_vertex.value_7L;
s_arcs[iloop_from_index][to_index] = GetOperationDistance (from_value_3L, from_value_7L, iloop_operation);
}
}
}
}
void ShortestPath_DIJ ()
{
int iloop = 0;
int iloop_tmp = 0;
int iloop_v = 0;
int current_v = 0;
int iloop_w = 0;
//Init the paths:
for (iloop = 0; iloop < MAX_VERTEX_NUM; iloop ++)
{
for (iloop_tmp = 0; iloop_tmp < MAX_VERTEX_NUM; iloop_tmp ++)
{
s_path[iloop][iloop_tmp] = ERROR_VERTEX;
}
}
//Init distances: From start vertex to other vertex which can directly reach to.
for (iloop = 0; iloop < MAX_VERTEX_NUM; iloop ++)
{
s_shortest_distance[iloop] = s_arcs[s_start_vertex][iloop];
s_exist_path[s_start_vertex][MAX_VERTEX_NUM] = 1;
s_shortest_vertex_gather[iloop] = 0;
}
//Search the shortest distance vertex "one by one"
for (iloop = 1; iloop < MAX_VERTEX_NUM; iloop ++) //start vertex can be removed, so iloop = 1, not 0;
{
int min = MAX_DISTANCE;
//pick out shortest connected vertex to gather V
for (iloop_v = 0; iloop_v < MAX_VERTEX_NUM; iloop_v ++)
{
if (s_shortest_vertex_gather[iloop_v] == 0
&& s_shortest_distance[iloop_v] < min)
{
min = s_shortest_distance[iloop_v]; //from "s_start_vertex" to shortest vertex which index is "iloop_v"
current_v = iloop_v;
for (iloop_tmp = 0; iloop_tmp < MAX_VERTEX_NUM; iloop_tmp ++)
{
if (s_path[current_v][iloop_tmp] == ERROR_VERTEX)
{
s_path[current_v][iloop_tmp] = current_v;
break;
}
}
}
}
s_shortest_vertex_gather[current_v] = 1; //add the vertex to gather V;
//set the distance which connected with "current_v" vertex
for (iloop_w = 0; iloop_w < MAX_VERTEX_NUM; iloop_w ++)
{
if (s_shortest_vertex_gather[iloop_w] != 1 //Not in gather V
&& (min + s_arcs[current_v][iloop_w] < s_shortest_distance[iloop_w])) //current_v vertex connected with iloop_w vertex
{
s_shortest_distance[iloop_w] = min + s_arcs[current_v][iloop_w];
s_exist_path[current_v][iloop_w] = 1;
memcpy (&s_path[iloop_w][0], &s_path[current_v][0], sizeof(int) * ERROR_VERTEX);
for (iloop_tmp = 0; iloop_tmp < MAX_VERTEX_NUM; iloop_tmp ++)
{
if (s_path[iloop_w][iloop_tmp] == ERROR_VERTEX)
{
s_path[iloop_w][iloop_tmp] = iloop_w;
break;
}
}
}
}
}
}
int main ()
{
InitDijkstraArcs ();
ShortestPath_DIJ ();
return 0;
}
#elif defined INPUT_OUTPUT_MODE
int GetOperationStepsByInputOutCount (int count_3l, int count_7l)
{
//We should ensure operation steps: total "input > output"
}
int CountOne (int value)
{
int iloop = 0;
int count = 0;
for (iloop = 0; iloop < 32; iloop ++)
{
if ((value & (0x01 << iloop)))
{
count ++;
}
}
return count;
}
void main ()
{
int iloop_count_3l = 0;
int iloop_count_7l = 0;
int count_3l = 0; //> 0 means INPUT,
int count_7l = 0;
int min = MAX_IN_WATER;
int total_count = 0; //include input/output
int iloop_total_operation = 0; //how many conbinations for INPUT/OUTPUT
int operation_result = 0; //how many conbinations for INPUT/OUTPUT
int iloop_bit = 0;
int current_contains = 0;
//Get input/out count
for (iloop_count_3l = -10; iloop_count_3l < 10; iloop_count_3l ++)
{
for (iloop_count_7l = -10; iloop_count_7l < 10; iloop_count_7l ++)
{
if (iloop_count_3l * CONTAINER_3L + iloop_count_7l * CONTAINER_7L == CONTAINER_TARGET)
{
int input = 0;
if (iloop_count_3l > 0)
input += iloop_count_3l * CONTAINER_3L;
if (iloop_count_7l > 0)
input += iloop_count_7l * CONTAINER_7L;
if (min > input)
{
min = input;
count_3l = iloop_count_3l;
count_7l = iloop_count_7l;
}
printf ("iloop_count_3l == %d, iloop_count_7l == %d \n", iloop_count_3l, iloop_count_7l);
}
}
}
//total_count
if (count_3l < 0)
{
total_count = (-count_3l) + count_7l;
}
else if (count_7l < 0)
{
total_count = (-count_7l) + count_3l;
}
// use the binary bit: 1 means input, 0 means output
for (iloop_total_operation = 0; iloop_total_operation < (0x01 << total_count); iloop_total_operation ++)
{
int one_num = CountOne (iloop_total_operation);
if (count_3l > 0 && one_num == count_3l) //input 3L
{
for (iloop_bit = 0; iloop_bit < total_count; iloop_bit ++)
{
if (iloop_total_operation & (0x01 << iloop_bit)) //IN
{
current_contains += CONTAINER_3L;
}
else //OUT
{
current_contains -= CONTAINER_7L;
}
//This operation is invalid
if (current_contains < 0 || current_contains > 10)
break;
if (current_contains == CONTAINER_TARGET)
{
operation_result = iloop_total_operation;
break;
}
}
}
else if (count_7l > 0 && one_num == count_7l) //input 7L
{
for (iloop_bit = 0; iloop_bit < total_count; iloop_bit ++)
{
if (iloop_total_operation & (0x01 << iloop_bit)) //IN
{
current_contains += CONTAINER_7L;
}
else //OUT
{
current_contains -= CONTAINER_3L;
}
//This operation is invalid
if (current_contains < 0 || current_contains > 10)
break;
if (current_contains == CONTAINER_TARGET)
{
operation_result = iloop_total_operation;
break;
}
}
}
current_contains = 0; //clear status.
if (operation_result)
return operation_result;
}
}
#else
void main ()
{
Node_T current_node = {0, 0, IN_3L}; //
int total = 0;
InitStatusOperationMap ();
//Create first node
current_node.value_3L = 0;
current_node.value_7L = 0;
current_node.operation = IN_3L;
//Push stack
memcpy(&s_statck_array[s_statck_index], ¤t_node, sizeof(current_node));
s_statck_index ++; //
//Not Finish Work: Top stack check, whether finish work
while (s_statck_array[s_statck_index - 1].value_7L != CONTAINER_TARGET)
{
//Not the error last operation
while (s_statck_array[s_statck_index - 1].operation < E_OPERATION_ERROR
&& JudgeTopNodeValid (s_statck_array[s_statck_index - 1]) != 1)
{
s_statck_array[s_statck_index - 1].operation ++;
}
//Error operation, there is no valid operation can be excuted, so pop stack
//Pop stack
if (s_statck_array[s_statck_index - 1].operation >= E_OPERATION_ERROR)
{
s_statck_array[s_statck_index].value_3L = 0;
s_statck_array[s_statck_index].value_7L = 0;
s_statck_array[s_statck_index].operation = IN_3L;
s_statck_index --;
if (s_statck_index == 0)
return;
//Previous top stack node, try to use "Next operation"
s_statck_array[s_statck_index - 1].operation ++;
}
else
{
OperateResult (s_statck_array[s_statck_index - 1], ¤t_node);
current_node.operation = IN_3L;
memcpy(&s_statck_array[s_statck_index], ¤t_node, sizeof(current_node));
s_statck_index ++;
}
}
total = GetStackTotalWater ();
if (s_total_min > total)
{
s_total_min = total;
}
printf ("Finish work: s_total_min = %d \n", s_total_min);
return;
}
#endif
- 2个空水壶,容积分别为3升和7升,如何只用这2个水壶从池塘里取得5升的水 -- 之程序实现
- 假设有一个池塘,里面有无穷多的水。现有2个空水壶,容积分别为5升和7升。问题是如何只用这2个水壶从池塘里取得6升的水?
- 题解分析及总结:经典逻辑面试题“假设有一个池塘,里面有无穷多的水,现有2个空水壶,如何使用少于15L的水,用2个水壶从池塘里取得3升水”
- 水壶
- 去除热水壶里的污垢
- 水壶、茶叶罐和我
- 闷水壶的冒险码头
- 请马上停用这种水壶,长期喝它烧的水,后果很严重!很多人家里几乎都用!
- bzoj4242: 水壶
- 4242: 水壶
- margin或者padding值为4个、3个、2个、1个的时候分别是什么意思
- 算法进化历程之“水壶问题”
- 只用2GB内在20亿个整数里中找到出现次数最多的数
- 满满一水壶的寻常事
- 昨天买了个运动水壶,到网上查了下关于塑料循环标志,保存下
- 如何只用一个大小为10的数组或列表来排序1000个随机整数?
- 代码解题之“*升水,有个*升,和*升的空桶,让你取出*升水”
- 水壶再一次爆了!!!
- DNS协议
- servlet和struts同时使用时
- 【JavaScript 】JavaScript 的性能优化:加载和执行
- 欢迎使用CSDN-markdown编辑器
- 3.Android-传感器开发-处理各种传感器配置
- 2个空水壶,容积分别为3升和7升,如何只用这2个水壶从池塘里取得5升的水 -- 之程序实现
- 8位灰度图两次一维卷积高斯模糊(VC++)
- IPv6过渡技术介绍-一
- Web开发者不可不知的15条编码原则
- libvirt 虚拟机迁移配置
- vi查找替换命令详解
- php面向对象(OOP)—__set(),__get(),__isset(),__unset()
- 第十四周阅读项目(1)
- Android传感器的运用之ACCELEROMETER