2个杯子 容积分别为a和b (int型 大于0) 想用这两个杯子称出c升水(c也是int型 大于0)
要求 a b c全部由用户输入 然后写出每一步的详细情况 并且 每一步只能动一个杯子
比如 a=1 b=2 要求称3升水 步骤为
1,0
1,2
每次只能给一个杯子装水(即不能直接输出1,2) 倒水也一样
最后再屏幕上输出这些步骤 要求是最简步骤这个算法 怎么做哇......有什么思路么......
要求 a b c全部由用户输入 然后写出每一步的详细情况 并且 每一步只能动一个杯子
比如 a=1 b=2 要求称3升水 步骤为
1,0
1,2
每次只能给一个杯子装水(即不能直接输出1,2) 倒水也一样
最后再屏幕上输出这些步骤 要求是最简步骤这个算法 怎么做哇......有什么思路么......
c%(a+b) c%|(a-b)|
|| 是绝对值也有可能无解。
本人愚见,也请高人斧正。
{
int a, b, c;
Console.WriteLine("请先输入A容器大小:");
a = Int32.Parse(Console.ReadLine());
Console.WriteLine("输入B容器大小:");
b = Int32.Parse(Console.ReadLine()); Console.WriteLine("输入C大小:");
c = Int32.Parse(Console.ReadLine()); int mod = 0,count; count = c / (a > b ? a : b);
mod = c % (a > b ? a : b) ;
if (mod == 0)
{
for (int i = 1; i <= count; i++)
{
Console.WriteLine("第" + i.ToString() + "步:" + (a > b ? a : b).ToString() + ":" + (a > b ? a : b).ToString() + " " + ((a > b ? b : a).ToString()) + ":0");
}
}
else
{
bool flog = false;
for (int i = count; i > 0; i--)
{
if ((c - i * (a > b ? a : b)) % (a > b ? b : a) == 0)
{
for (int j = 1; j <= i; j++)
{
Console.WriteLine("第" + j.ToString() + "步:" + (a > b ? "a" : "b") + ":" + (a > b ? a : b).ToString() + " " + (a > b ? "b" : "a") + ":0");
}
for (int j = i + 1; j < (c - i * (a > b ? a : b)) / (a > b ? b : a) + i + 1; j++)
{
Console.WriteLine("第" + j.ToString() + "步:" + (a > b ? "a" : "b") + ":0 " + (a > b ? "b" : "a") + ":" + (a > b ? b : a).ToString());
}
flog = true;
}
}
if (!flog)
{
Console.WriteLine("无法测量!最后剩余:" + ((c % (a > b ? a : b)) % (a > b ? b : a)).ToString()); }
}
Console.ReadLine();
}
{
int a, b, c;
Console.WriteLine("请先输入A容器大小:");
a = Int32.Parse(Console.ReadLine());
Console.WriteLine("输入B容器大小:");
b = Int32.Parse(Console.ReadLine()); Console.WriteLine("输入C大小:");
c = Int32.Parse(Console.ReadLine()); int mod = 0,count;
if (c < (a > b ? b : a))
{
Console.WriteLine("无法测量!最后剩余:" + (a > b ? b : a).ToString());
Console.ReadLine();
return;
}
else if (c < (a > b ? a : b))
{
mod = c % (a > b ? b : a);
count = c / (a > b ? b : a);
if (mod == 0)
{
for (int i = 1; i <= count; i++)
{
Console.WriteLine("第" + i.ToString() + "步:" + (a > b ? "a" : "b") + ":0 " + (a > b ? "b" : "a") + ":" + (a > b ? b : a).ToString());
}
}
else
{
Console.WriteLine("无法测量!最后剩余:" + (c % (a > b ? b : a)).ToString());
}
Console.ReadLine();
return;
}
else
{
count = c / (a > b ? a : b);
mod = c % (a > b ? a : b);
if (mod == 0)
{
for (int i = 1; i <= count; i++)
{
Console.WriteLine("第" + i.ToString() + "步:" + (a > b ? "a" : "b") + ":" + (a > b ? a : b).ToString() + " " + (a > b ? "b" : "a") + ":0");
}
}
else
{
bool flog = false;
for (int i = count; i > 0; i--)
{
if ((c - i * (a > b ? a : b)) % (a > b ? b : a) == 0)
{
for (int j = 1; j <= i; j++)
{
Console.WriteLine("第" + j.ToString() + "步:" + (a > b ? "a" : "b") + ":" + (a > b ? a : b).ToString() + " " + (a > b ? "b" : "a") + ":0");
}
for (int j = i + 1; j < (c - i * (a > b ? a : b)) / (a > b ? b : a) + i + 1; j++)
{
Console.WriteLine("第" + j.ToString() + "步:" + (a > b ? "a" : "b") + ":0 " + (a > b ? "b" : "a") + ":" + (a > b ? b : a).ToString());
}
flog = true;
break;
}
}
if (!flog)
{
Console.WriteLine("无法测量!最后剩余:" + ((c % (a > b ? a : b)) % (a > b ? b : a)).ToString()); }
}
}
Console.ReadLine();
}
可惜好像还是无法测量啊。其实算法应该跟输出分离开。算法就是搜索出“倒满、倒入、倒空”这三种操作行为的一个IEnumeable<MyAction>列表,实际上使用.net迭代器,可能用不了15行语句就能枚举出操作序列来。当然要是求最简,则需要另外一个Linq查询来遍历所有解答。
c%|(a+b)| 和 c %|(a-b)| 有余数的情况。
c%a c%b 这些都不等于0时,就无解了。 总结下就是 c%(na+mb) <> 0 (任何一组都不成立时)
这只是特例,其实还有(Na-b) 或(nb - b)等等。
如: a = 5 b = 5 c = 1就是无解的情况 。
情况 比我刚看到时估计的复杂些。
先算出C和A的余数mod,C/A的值count,
如果mod和B取余不等于0说明不可行,然后C=(count-1)乘A,然后再判断C和B的余数,如果仍不为0,则继续。知道C=C的时候在判断C和B的余数,如果还是不为零,则说明不能测量。
中间只要出现等于0的情况,就说明可以测量的,并且肯定是最简步骤,因为,在循环中已经用A最大可能性的量出。
就是上面的数据,a=3、b=7、c=5,没有给出答案。
我改进后的是答案是:
请先输入A容器大小:
3
输入B容器大小:
7
输入C大小:
5
无法测量!最后剩余:2
刚开始是按照自己的思路一行一行的写,没有考虑到代码优化。
不过当C特别大,A和B特别小,比如都等于1 的时候,我现在写的代码是不是要比用递归效率高些?毕竟少了来回调用函数了么、O(∩_∩)O~
using System;namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
int a = 3, b = 5, c = 7;
int countA, countB;
EuclidExtend(a, b, out countA, out countB);
countA *= c;
countB *= c; int temp = countA / b;
countA -= temp * b;
countB += temp * a; if (Math.Abs(countA) + Math.Abs(countB) > Math.Abs(countA + b) + Math.Abs(countB - a))
{
countA += b;
countB -= a;
} if (Math.Abs(countA) + Math.Abs(countB) > Math.Abs(countA - b) + Math.Abs(countB + a))
{
countA -= b;
countB += a;
} Console.WriteLine("{0} = ({1}*{2}) + ({3}*{4})", c, a, countA, b, countB);
} public static int EuclidExtend(int X, int Y, out int A, out int 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); int Temp = A; A = B; B = Temp - quotient * A;
return gcd;
}
}
}
c%(na-mb), 有这么一种情况,象 a = 2 b = 5 c = 1,
是否有解,其实 你看 5 - 2*2 = 1了。
因为c只有一个,一次只能移一个杯,所以,
c%(na-mb)中,n,m 必有一个为1.
我觉得你可能要搜索四种情况 :
c%a c%b c%(ma-nb) c%(ma+nb)
考虑,让 n = 0 ,1,3式就相等了。 让m = 0, 2 4式就相等了。
只考虑两种情况 (m,n必须一个为1),
递推下去应该可以解决。
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()重载成输出,就应该可以了。
// 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++;
}
还是有个地方错了, 用这个替换 。
//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);
}
using System;namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
int a = 1597, b = 2584, c = 198787;
int countA, countB; if (!Linear(a, b, c, out countA, out countB))
Console.WriteLine("无解"); int temp = a > b ? Math.Abs(countB / a) : Math.Abs(countA / b);
int flag = countA < 0 ? 1 : -1;
int minA = 0, minB = 0, minSum = int.MaxValue; for (int i = temp - 1; i <= temp + 1; i++)
{
int 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, minA, b, minB);
} public static int EuclidExtend(int X, int Y, out int A, out int 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); int Temp = A; A = B; B = Temp - quotient * A;
return gcd;
} public static bool Linear(int X, int Y, int N, out int A, out int B)
{
int gcd = EuclidExtend(X, Y, out A, out B);
int K = N / gcd; if (N != K * gcd) { A = 0; B = 0; return false; } A *= K; B *= K;
return true;
}
}
}
{
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;
}
}
}
A=30;
B=70;
C=2;
仅仅在脑海里输入这3个参数,我都无法得出答案,别说编程了
C是假想的无穷大的容器
杯子的属性: 容积 水量 剩余容积
方法 从杯子x向杯子y倒入z升的水
我的思路 数据库 表 存储过程/函数 递归 事务
回滚条件:出现已出现过的杯子存水状态,
终止条件:出现解/杯子1所有操作都递归过
1,2况且您真的认为您给出的那么长的序列会比我给出的“奇怪的数学公式”更好验证么?不要说3个杯子,就是100个杯子,求最优都可以用动态规划来解(DP),只要C不是很大,都可以在内存中完成计算。这只是一个入门级的算法题,相信里人工智能还有很远的距离,最多也就是考察一下算法设计者的“智能”。可以放心的是,绝对不会惊动到数学家的,像我这样的小程序员就可以搞定。作为程序员讨论这个算法,我可以说,用欧几里得扩展的方法,时间复杂度是O(Log(n))的,用动态规划的方法,时间复杂度要高很多,是O(m*n)的,其中n是c取值的范围,m是杯子的个数。以上两个程序都可以在100行代码以内解决问题,绝不是什么高科技。而您所提到的“人工智能搜索”,复杂度如何呢?