面试遇到的算法题:两个杯子量水

diyuhou 2010-11-16 08:10:56
2个杯子 容积分别为a和b (int型 大于0) 想用这两个杯子称出c升水(c也是int型 大于0)
要求 a b c全部由用户输入 然后写出每一步的详细情况 并且 每一步只能动一个杯子
比如 a=1 b=2 要求称3升水 步骤为
1,0
1,2
每次只能给一个杯子装水(即不能直接输出1,2) 倒水也一样
最后再屏幕上输出这些步骤 要求是最简步骤

这个算法 怎么做哇......有什么思路么......
...全文
1456 49 打赏 收藏 转发到动态 举报
写回复
用AI写文章
49 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
我在41楼给出的三个杯子的规划结果是一个可行的操作步骤,但是其实用眼睛“运行”几步就会发现算法的问题,我没有随机选择3个杯子中的一个而是顺序选择,并且对于可行的操作没有随机打乱次序去尝试而是按照“倒满、倒空、顺序选择其它杯子并倒水”这样的僵化的次序、而非启发的次序去查找。但是因为我强调了最基本的要求、结构、算法,如果连方向都错了,根本不顾实际题目要打印出操作次序这个前提,那么我也没有必要写出程序来说明“人工智能搜索程序”到底是个什么模式的,那么这个面试题目也就失败了,这个题目没有面试到程序员反而面试到数学家了。
whrspsoft3723 2010-11-17
  • 打赏
  • 举报
回复
还是贴个完整版吧。 不知是否有漏洞,请大家指正。

void test(int a, int b, int c) {
//swap a,b resut = a > b
if(a < b){
int k = b;
b = a;
a = k;
}

int m = 1,n = 0;

if (c % a == 0 || c % b == 0) {
Debug("OK");
return;
}

// n = 1, m >= 1
m = 1;
while (c > m * a - b) {
if (c % (m * a - b) == 0) {
Debug(string.Format("{0} * {1} - {}2",m,a,b));
return;
}

m++;
}


//m = 1,n >= 1
n = 1;
while (c > a - n*b && a - n*b > 0) {
if (c % (a - n*b) == 0) {
Debug(string.Format("{0} - {1} * {2}",a,n,b));
return;
}
n++;
}

//-------------------------
// m = 1,n >= 1
n = 1;
while (c > a + n*b) {
if (c % (a + n*b) == 0) {
Debug(string.Format("a + n*b = {0} + {1}* {2}",a,n,b));
return;
}

n++;
}

//3 n = 1, m >= 1
m = 1;
while (c > m*a + b ) {
if (c % (m*a + b) == 0) {
Debug(string.Format("m*a + b = {0}*{1} + {2}",m,a,b));
return;
}
m++;
}

Debug("无解");
}

void Debug(string s) {
MessageBox.Show(s);
}

  • 打赏
  • 举报
回复
不但知道做什么而且尤其知道怎么做(给出规划结果可以让不懂数学的人去验证),要比纯粹论证,重要多了。
whrspsoft3723 2010-11-17
  • 打赏
  • 举报
回复


//-------------------------
// m = 1,n >= 1
n = 1;
while (c > a + n*b) {
if (c % (a + n*b) == 0) {
Debug(string.Format("a + n*b = {0} + {1}* {2}",a,n,b));
return;
}

n++;
}




还是有个地方错了, 用这个替换 。
  • 打赏
  • 举报
回复
“人工智能”的前提首先是真实,凡是真实的但是不容易用人来规划的都可以算作人工智能。如果给出一堆数学公式,给过无法用不懂数学的普通人所理解的话把答案说出来,那么当然只能回避“智能”这个要求。

如果不能给出普通人都懂的真实语言描述,那么玩数学、程序有什么现实的意思?
binadan 2010-11-17
  • 打赏
  • 举报
回复
可以试想有3个容器A B 和C
C是假想的无穷大的容器
杯子的属性: 容积 水量 剩余容积
方法 从杯子x向杯子y倒入z升的水
我的思路 数据库 表 存储过程/函数 递归 事务
回滚条件:出现已出现过的杯子存水状态,
终止条件:出现解/杯子1所有操作都递归过

whrspsoft3723 2010-11-17
  • 打赏
  • 举报
回复

void test(int a, int b, int c) {
//swap a,b resut = a > b
if(a < b){
int k = b;
b = a;
a = k;
}

int m = 1,n = 0;

if (c % a == 0 || c % b == 0) {
Debug("OK");
return;
}

// n = 1, m >= 1
m = 1;
while (c > m * a - b) {
if (c % (m * a - b) == 0) {
Debug(string.Format("{0} * {1} - {}2",m,a,b));
return;
}

m++;
}


//m = 1,n >= 1
n = 1;
while (c > a - n*b && a - n*b > 0) {
if (c % (a - n*b) == 0) {
Debug(string.Format("{0} - {1} * {2}",a,n,b));
return;
}
n++;
}

//-------------------------
// m = 1,n >= 1
n = 1;
while (c > a - n*b) {
if (c % (a - n*b) == 0) {
Debug(string.Format("a - n*b = {0} - {1}* {2}",a,n,b));
return;
}

n++;
}

//3 n = 1, m >= 1
m = 1;
while (c > m*a + b ) {
if (c % (m*a + b) == 0) {
Debug(string.Format("m*a + b = {0}*{1} + {2}",m,a,b));
return;
}
m++;
}

Debug("无解");
}



void Debug(string s) {
MessageBox.Show(s);
}



这个应该可以了, 只是没有打印出来过程。
在循环中加入debug
debug()重载成输出,就应该可以了。

  • 打赏
  • 举报
回复
唉,只说空的没意思。比如出这样一个题目,三个杯子分别有3升、7升,20升,要求量出11升水来,如何找出一个相对快的倒法?

必须打印出操作步骤,弄数学公式是无法实际去操作的(比如产生指令,或者让人容易地看出对错)。

比如我打印一个倒法:

倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
从3升杯子向20升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
从3升杯子向20升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
从3升杯子向20升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
从3升杯子向20升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
从3升杯子向20升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
从3升杯子向20升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
从3升杯子向20升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
从3升杯子向20升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
从3升杯子向20升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
从3升杯子向20升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
从3升杯子向7升杯子倒水
倒满3升杯子
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
倒空3升杯子
从7升杯子向3升杯子倒水
从3升杯子向20升杯子倒水
绿色夹克衫 2010-11-17
  • 打赏
  • 举报
回复
3个以上的杯子用DP可以,前提是C不能太大,100万以内的话可以,实际上是一个背包问题,也是算法问题,还不涉及“智能”

[Quote=引用 37 楼 sp1234 的回复:]

其实这个题目出的缺乏“智能”,如果给3个以上的杯子,才能体现一些智能特点。
[/Quote]
wdzr_826 2010-11-17
  • 打赏
  • 举报
回复
[Quote=引用 36 楼 sp1234 的回复:]

引用 34 楼 microtry 的回复:
看见楼主的题目,感觉自己变NC了,
A=30;
B=70;
C=2;
仅仅在脑海里输入这3个参数,我都无法得出答案,别说编程了


故意加个0就过分了。3、7、2能不能口算得出答案?
[/Quote]
30.70.2肯定是没答案的。
3.7.2
那3升的一致往7升的里面倒,倒满7升的,3升里面剩两胜
  • 打赏
  • 举报
回复
其实这个题目出的缺乏“智能”,如果给3个以上的杯子,才能体现一些智能特点。
  • 打赏
  • 举报
回复
[Quote=引用 34 楼 microtry 的回复:]
看见楼主的题目,感觉自己变NC了,
A=30;
B=70;
C=2;
仅仅在脑海里输入这3个参数,我都无法得出答案,别说编程了
[/Quote]

故意加个0就过分了。3、7、2能不能口算得出答案?
  • 打赏
  • 举报
回复
[Quote=引用 34 楼 microtry 的回复:]
看见楼主的题目,感觉自己变NC了,
A=30;
B=70;
C=2;
仅仅在脑海里输入这3个参数,我都无法得出答案,别说编程了
[/Quote]

30、70、2?
缪军 2010-11-17
  • 打赏
  • 举报
回复
看见楼主的题目,感觉自己变NC了,
A=30;
B=70;
C=2;
仅仅在脑海里输入这3个参数,我都无法得出答案,别说编程了
zhubo006 2010-11-17
  • 打赏
  • 举报
回复
nmjyxl 2010-11-17
  • 打赏
  • 举报
回复
学习了
达不溜来多多 2010-11-17
  • 打赏
  • 举报
回复
有人去给我的那个问题随便回贴吗 我结贴50分
绿色夹克衫 2010-11-17
  • 打赏
  • 举报
回复
to:sp1234牛

您把问题弄复杂了,按照LZ原题的要求,我的程序只输出了“奇怪的数学公式”,比如58 = 5 * 11 + 3(5和3是杯子的容量),但这个真的很难理解么?讨论算法点到为止即可,我只是说这个算法的思路,并不是要替LZ写出具体程序。如果真的按照ACM的标准,您给出的输出同样是不合标准的,LZ要求的是:

1,0
1,2

况且您真的认为您给出的那么长的序列会比我给出的“奇怪的数学公式”更好验证么?

不要说3个杯子,就是100个杯子,求最优都可以用动态规划来解(DP),只要C不是很大,都可以在内存中完成计算。这只是一个入门级的算法题,相信里人工智能还有很远的距离,最多也就是考察一下算法设计者的“智能”。可以放心的是,绝对不会惊动到数学家的,像我这样的小程序员就可以搞定。

作为程序员讨论这个算法,我可以说,用欧几里得扩展的方法,时间复杂度是O(Log(n))的,用动态规划的方法,时间复杂度要高很多,是O(m*n)的,其中n是c取值的范围,m是杯子的个数。以上两个程序都可以在100行代码以内解决问题,绝不是什么高科技。而您所提到的“人工智能搜索”,复杂度如何呢?
showjim 2010-11-17
  • 打赏
  • 举报
回复
看了这个贴子,有一个感慨:软件与算法什么时候变得不相干了?
绿色夹克衫 2010-11-17
  • 打赏
  • 举报
回复
果然有bug,发现了,顺便改成了long,自己再测测!

using System;

namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
int a = 1597, b = 2584, c = 198787;
long countA, countB;

int gcd = EuclidExtend(a, b, out countA, out countB);
int K = c / gcd;

if (c != K * gcd)
{
Console.WriteLine("无解");
return;
}

countA *= K; countB *= K; a /= gcd; b /= gcd;

int temp = a > b ? (int)Math.Abs(countB / a) : (int)Math.Abs(countA / b);
int flag = countA < 0 ? 1 : -1;
long minA = 0, minB = 0, minSum = int.MaxValue;

for (int i = temp - 1; i <= temp + 1; i++)
{
long sum = Math.Abs(countA + (i * b) * flag) + Math.Abs(countB - (i * a) * flag);
if (sum < minSum)
{
minA = countA + (i * b) * flag;
minB = countB - (i * a) * flag;
minSum = sum;
}
}

Console.WriteLine("{0} = ({1}*{2}) + ({3}*{4})", c, a * gcd, minA, b * gcd, minB);
}

public static int EuclidExtend(int X, int Y, out long A, out long B)
{
if (Y == 0) { A = 1; B = 0; return X; }

int quotient = X / Y;
int gcd = EuclidExtend(Y, X - Y * quotient, out A, out B);

long Temp = A; A = B; B = Temp - quotient * A;
return gcd;
}
}
}
加载更多回复(28)
内容概要:本文围绕“新型电力系统下多分布式电源接入配电网承载力评估方法”的研究,系统性地介绍了基于Matlab的仿真建模与代码实现方案,旨在评估高比例分布式电源(如光伏、风电等)接入背景下配电网的接纳能力。研究融合了智能优化算法(如蜣螂优化、灰狼优化、遗传算法)、多目标优化、鲁棒优化及双层优化模型,结合潮流计算、稳定性分析与故障仿真,构建了完整的承载力评估体系。文档不仅提供核心算法实现,还拓展至微电网调度、储能配置、电氢耦合系统、电动汽车协同等前沿方向,强调“复现+创新”相结合的科研路径,助力研究者快速掌握高水平论文复现技巧并激发原创思路。; 适合人群:具备电力系统、自动化或相关专业背景,熟悉Matlab/Simulink仿真环境,正在从事科研或工程应用的研究生及初级科研人员(工作1-3年);; 使用场景及目标:①复现高水平期刊中关于配电网承载力的优化模型;②开展高比例可再生能源接入下的配电网规划与运行研究;③学习并应用智能优化算法解决复杂电力系统问;④获取完整科研资源包以加速课进展与论文撰写; 阅读建议:建议读者关注公众号“荔枝科研社”获取网盘资源,下载全套代码与模型文件,按照文档结构循序渐进学习,重点理解算法设计逻辑与仿真建模细节,结合所提供的复现案例深化对优化模型与工程应用场景的理解,提升科研效率与创新能力。

111,129

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧