自己备查:如何优化算法--缓存
题目:
http://projecteuler.net/index.php?section=problems&id=164
projecteuler.net #164
How many 20 digit numbers n (without any leading zero) exist such that no three consecutive digits of n have a sum greater than 9?
使用简单算法,从高位到低位便利每种组合,慢的要死
View Code
List<int> number = new List<int>();
int count = 0;
public object Run()
{
for (int i = 0; i < 10; i++)
{
//number.Add(i);
Run2(1, i, 0);
//number.RemoveAt(0);
}
return count;
}
void Run2(int level, int last, int lastlast)
{
for (int i = 0, length = 9 - last - lastlast; i <= length; i++)
{
if (level == 2)
{
Console.WriteLine("" + lastlast + last + i);
}
//if (level > 1 && last + lastlast + i > 9)
// return;
if (level == 6)
{
count += 1;
return;
}
//number.Add(i);
Run2(level + 1, i, last);
//number.RemoveAt(level);
}
}
int count = 0;
public object Run()
{
for (int i = 0; i < 10; i++)
{
//number.Add(i);
Run2(1, i, 0);
//number.RemoveAt(0);
}
return count;
}
void Run2(int level, int last, int lastlast)
{
for (int i = 0, length = 9 - last - lastlast; i <= length; i++)
{
if (level == 2)
{
Console.WriteLine("" + lastlast + last + i);
}
//if (level > 1 && last + lastlast + i > 9)
// return;
if (level == 6)
{
count += 1;
return;
}
//number.Add(i);
Run2(level + 1, i, last);
//number.RemoveAt(level);
}
}
优化后,从低位到高位递增,每次缓存当位所有ok的数字以及对应的可能性供下位处理,时间复杂度O(n),瞬间完成
View Code
class Problem164 : IProblem
{
Dictionary<int, C> last = new Dictionary<int, C>();
Dictionary<int, C> current = new Dictionary<int, C>();
public object Run()
{
int l, ll;
for (int i = 0; i < 100; i++)
{
l = i / 10;
ll = i % 10;
if (l + ll < 10)
last.Add(i, new C(l, ll, 1));
}
return Run2(2);
}
public long Run2(int level)
{
int thisLevelBegin = (level == 19 ? 1 : 0);
current = new Dictionary<int, C>();
int l, ll, sum, newNum;
long count;
foreach (KeyValuePair<int, C> p in last)
{
l = p.Value.L;
ll = p.Value.LL;
count = p.Value.count;
sum = p.Value.sum;
for (int i = thisLevelBegin, length = 10 - sum; i < length; i++)
{
newNum = i * 10 + l;
if (!current.ContainsKey(newNum))
{
current.Add(newNum, new C(i, l, count));
}
else
{
current[newNum].count += count;
}
}
}
if (level == 19)
{
count = 0;
foreach (KeyValuePair<int, C> p in current)
{
count += p.Value.count;
}
return count;
}
last = current;
return Run2(level + 1);
}
}
class C
{
public int LL;
public int L;
public int sum;
public long count;
public C(int l, int ll, long c)
{
LL = ll;
L = l;
count = c;
sum = l + ll;
}
}
{
Dictionary<int, C> last = new Dictionary<int, C>();
Dictionary<int, C> current = new Dictionary<int, C>();
public object Run()
{
int l, ll;
for (int i = 0; i < 100; i++)
{
l = i / 10;
ll = i % 10;
if (l + ll < 10)
last.Add(i, new C(l, ll, 1));
}
return Run2(2);
}
public long Run2(int level)
{
int thisLevelBegin = (level == 19 ? 1 : 0);
current = new Dictionary<int, C>();
int l, ll, sum, newNum;
long count;
foreach (KeyValuePair<int, C> p in last)
{
l = p.Value.L;
ll = p.Value.LL;
count = p.Value.count;
sum = p.Value.sum;
for (int i = thisLevelBegin, length = 10 - sum; i < length; i++)
{
newNum = i * 10 + l;
if (!current.ContainsKey(newNum))
{
current.Add(newNum, new C(i, l, count));
}
else
{
current[newNum].count += count;
}
}
}
if (level == 19)
{
count = 0;
foreach (KeyValuePair<int, C> p in current)
{
count += p.Value.count;
}
return count;
}
last = current;
return Run2(level + 1);
}
}
class C
{
public int LL;
public int L;
public int sum;
public long count;
public C(int l, int ll, long c)
{
LL = ll;
L = l;
count = c;
sum = l + ll;
}
}