1.最大子数组
问题不在描述,按照算法导论所提供的分治思想 对于
一个数组,要想存在最大子数组,必须存在负数,这样问题才存在意义。
利用分治思想,将一个数组分成两部分,最大子数组肯定存在于这两个子数组
之一或者是一个跨过中点的数组。
代码如下
#include<iostream>
#include<vector>
using namespace std;
int left_low = 0, left_high = 0, left_sum = 0;
int right_low = 0, right_high = 0, right_sum = 0;
int mid_low = 0, mid_high = 0, mid_sum = 0;
vector<int> findmid(vector<int> a, int l,int mid, int r)//算出跨越中点的最大子数组
{
int left_sum = -200;
int left_low = 0;
int sum =0;
int right_sum = -200;
int right_high = 0;
for (int i = mid; i >= l; i--)
{
sum = a[i]+sum;
if (sum > left_sum)
{
left_low = i;
left_sum = sum;
}
}
sum = 0;
for (int i = mid+1; i <= r; i++)
{
sum = a[i]+sum;
if (sum >right_sum)
{
right_high = i;
right_sum = sum;
}
}
return{ left_low, right_high, left_sum + right_sum };
}
vector<int> find(vector<int> a, int r, int l)
{
if (l == r)
{
return{ r, l, a[r] };
}
else
{
int mid = (l + r) / 2;
vector<int>a0 = find(a, r, mid);
left_low = a0[0];
left_high = a0[1];
left_sum = a0[2];
vector<int>b = find(a, mid + 1, l);
right_low = b[0];
right_high = b[1];
right_sum = b[2];
vector<int> c = findmid(a, r, mid, l);
mid_low = c[0];
mid_high = c[1];
mid_sum = c[2];
if (left_sum >= right_sum&&left_sum>=mid_sum)
{
return{ left_low, left_high, left_sum };
}
else
{
if (right_sum>=left_sum&&right_sum >= mid_sum)
return{ right_low, right_high, right_sum };
else
return{ mid_low, mid_high, mid_sum };
}
}
}
void main()
{
vector<int> a{13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
vector<int> b = find(a, 0, a.size()-1);
for (auto c : b)
cout << c << endl;
system("pause");
}
第二种解决方法是动态规划
我们定义两个变量,其中一个是sum_,max,另一个是sum,sum_max保留的当前上一组
的最大值,而sum保存的是试探值,及当sum>sum_max的时候,把sum的值给sum_max
而当sum<0的时候意味着sum所加的元素不能代表最大子数组,应该从当前的一个元素
继续进行判断。
代码如下:
#include<iostream>
#include<vector>
using namespace std;
void pr(vector<int> a)
{
if (a.size() == 0)
{
cout << 0 << endl;
return;
}
int sum_max = 0;
int sum_max1 = 0;
int sum = 0;
int key = 0;
int key_1 = 0;
for (int i = 0; i <= a.size() - 1; i++)
{
sum += a[i];
if (sum < 0)
{
sum = 0;
key_1 = i + 1;
continue;
}
if (sum > sum_max)
{
sum_max = sum;
key = i;
}
}
cout << key_1 << " " << key << " " << sum_max;
}
void main()
{
vector<int> a{13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7 };
pr(a);
system("pause");
}
2.矩阵乘法
最简单的一种是n为2的幂的时候,以分治思想可以把a和b矩阵各自分成
4个,那么利用递归求解,而关于矩阵的分解,可以利用下标来进行表示
那么我们递归到最后其实处理的是最简单的乘法。
代码如下:
#include<iostream>
#include<vector>
using namespace std;
typedef vector<vector<int>> vector2;
void input(vector2&a, int n)
{
int m;
vector<int> c;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> m;
c.push_back(m);
}
a.push_back(c);
c.clear();
}
}
void mul(const vector2 a, const vector2 b,vector2 &c,int x,int y,int x1,int y1,int n)
{
if (n == 1)
{
c[x][y1] += a[x][y] * b[x1][y1];
}
else
{
n = n / 2;
mul(a, b, c, x, y, x1, y1, n);
mul(a, b, c, x, y+n, x1+n, y1, n);
mul(a, b, c, x, y, x1, y1+n,n);
mul(a, b, c, x, y+n, x1 + n, y1 + n, n);
mul(a, b, c, x+n, y, x1, y1,n);
mul(a, b, c, x+n, y + n, x1+n, y1, n);
mul(a, b, c, x+n, y, x1, y1+n,n);
mul(a, b, c, x+n, y +n, x1 + n, y1 + n, n);
}
}
void main()
{
vector2 a, b, c;
int n;
cin >> n;
if ( n % 2 != 0)
{
cout << "error" << endl;
}
else
{
input(a,n);
input(b,n);
for (int i = 0; i < n; i++)
{
vector<int> q;
for (int j = 0; j < n; j++)
{
int t = 0;
q.push_back(t);
}
c.push_back(q);
}
mul(a, b,c, 0, 0, 0, 0, n);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cout << c[i][j] << " ";
}
cout << endl;
}
}
system("pause");
}
2.strassen算法
这个算法的核心思想是另递归树的枝叶不那么茂盛一点,显然,他做到了
代码如下:
#include<iostream>
#include<vector>
using namespace std;
typedef vector<vector<int>> vector2;
void input(vector2&a, int n)
{
int m;
vector<int> c;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> m;
c.push_back(m);
}
a.push_back(c);
c.clear();
}
}
void mul(const vector2 a, const vector2 b, vector2 &c, int x, int y, int x1, int y1, int n)
{
if (n == 2)
{
n = n - 1;
int s[10];
s[0] = b[x1][y1 + n] - b[x1 + n][y1 + n];
s[1] = a[x][y] + a[x][y + n];
s[2] = a[x + n][y] + a[x + n][x + n];
s[3] = b[x1 + n][y1] - b[x1][y1];
s[4] = a[x][y] + a[x + n][y + n];
s[5] = b[x1][y1] + b[x1 + n][y1 + n];
s[6] = a[x][y + n] - a[x + n][y + n];
s[7] = b[x1 + n][y1] + b[x1 + n][y1 + n];
s[8] = a[x][y] - a[x + n][y];
s[9] = b[x1][y1] + b[x1][y1 + n];
int p[7];
p[0] = a[x][y] * s[0];
p[1] = s[1] * b[x1 + n][y1 + n];
p[2] = s[2] * b[x1][y1];
p[3] = s[3] * a[x + n][y + n];
p[4] = s[4] * s[5];
p[5] = s[6] * s[7];
p[6] = s[8] * s[9];
c[x][y1] += p[4] + p[3] - p[1] + p[5];
c[x][y1 + n] += p[0] + p[1];
c[x + n][y1] += p[2] + p[3];
c[x + n][y1 + n] += p[4] + p[0] - p[2] - p[6];
}
else
{
n = n / 2;
mul(a, b, c, x, y, x1, y1, n);
mul(a, b, c, x, y + n, x1 + n, y1, n);
mul(a, b, c, x, y, x1, y1 + n, n);
mul(a, b, c, x, y + n, x1 + n, y1 + n, n);
mul(a, b, c, x + n, y, x1, y1, n);
mul(a, b, c, x + n, y + n, x1 + n, y1, n);
mul(a, b, c, x + n, y, x1, y1 + n, n);
mul(a, b, c, x + n, y + n, x1 + n, y1 + n, n);
}
}
void main()
{
vector2 a, b, c;
int n;
cin >> n;
if (n % 2 != 0)
{
cout << "error" << endl;
}
else
{
input(a, n);
input(b, n);
for (int i = 0; i < n; i++)
{
vector<int> q;
for (int j = 0; j < n; j++)
{
int t = 0;
q.push_back(t);
}
c.push_back(q);
}
mul(a, b, c, 0, 0, 0, 0, n);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cout << c[i][j] << " ";
}
cout << endl;
}
}
system("pause");
}
这是求解n是2的幂的矩阵乘法,当n不是2的幂的时候,其实我们可以把矩阵
转换为2的幂,例如我们可以补0进行转换,我们可以知道矩阵乘法最后的
行数和列数,那么我们删除其他的数字就可以得到矩阵乘法的结果。
代码的改变只是增加了补充函数与删除函数
代码如下:
#include<iostream>
#include<vector>
#include<math.h>
using namespace std;
typedef vector<vector<int>> vector2;
/*
算法导论的strassen算法扩展,及满足n不是2的幂的情况
思路是变为2的幂,补0
最后去除0
*/#include<iostream>
#include<vector>
#include<math.h>
using namespace std;
typedef vector<vector<int>> vector2;
/*
算法导论的strassen算法扩展,及满足n不是2的幂的情况
思路是变为2的幂,补0
最后去除0
*/
void output(vector2 const &a,int x1,int y1)
{
for (int i = 0; i < x1; i++)
{
for (int j = 0; j < y1; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
}
void input(vector2 &a, int x1, int y1,int n)//补充的具体实现
{
vector<int> s;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (i < x1&&j < y1)
{
int t;
cin >> t;
s.push_back(t);
}
else
{
s.push_back(0);
}
}
a.push_back(s);
s.clear();
}
}
int padding (vector2&a, vector2 &b, int x1, int y1, int x2,int y2)//判断应该补充多少
{
int n = 6;//2的6次方已经极大
for (int i = 2; i <= n; i++)
{
int t = pow(2, i);
if (t >= x1)//判断n应该为多少
{
n = t;
break;
}
}
input(a, x1, y1, n);
input(b, x2, y2, n);
return n;
}
void mul(const vector2 a, const vector2 b, vector2 &c, int x, int y, int x1, int y1, int n)
{
if (n == 2)
{
n = n - 1;
int s[10];
s[0] = b[x1][y1 + n] - b[x1 + n][y1 + n];
s[1] = a[x][y] + a[x][y + n];
s[2] = a[x + n][y] + a[x + n][x + n];
s[3] = b[x1 + n][y1] - b[x1][y1];
s[4] = a[x][y] + a[x + n][y + n];
s[5] = b[x1][y1] + b[x1 + n][y1 + n];
s[6] = a[x][y + n] - a[x + n][y + n];
s[7] = b[x1 + n][y1] + b[x1 + n][y1 + n];
s[8] = a[x][y] - a[x + n][y];
s[9] = b[x1][y1] + b[x1][y1 + n];
int p[7];
p[0] = a[x][y] * s[0];
p[1] = s[1] * b[x1 + n][y1 + n];
p[2] = s[2] * b[x1][y1];
p[3] = s[3] * a[x + n][y + n];
p[4] = s[4] * s[5];
p[5] = s[6] * s[7];
p[6] = s[8] * s[9];
c[x][y1] += p[4] + p[3] - p[1] + p[5];
c[x][y1 + n] += p[0] + p[1];
c[x + n][y1] += p[2] + p[3];
c[x + n][y1 + n] += p[4] + p[0] - p[2] - p[6];
}
else
{
n = n / 2;
mul(a, b, c, x, y, x1, y1, n);
mul(a, b, c, x, y + n, x1 + n, y1, n);
mul(a, b, c, x, y, x1, y1 + n, n);
mul(a, b, c, x, y + n, x1 + n, y1 + n, n);
mul(a, b, c, x + n, y, x1, y1, n);
mul(a, b, c, x + n, y + n, x1 + n, y1, n);
mul(a, b, c, x + n, y, x1, y1 + n, n);
mul(a, b, c, x + n, y + n, x1 + n, y1 + n, n);
}
}
void main()
{
vector2 a, b, c;
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
if (y1 != x2)
{
cout << "error not *" << endl;
}
else
{
int n=padding(a, b, x1, y1, x2, y2);
for (int i = 0; i < n; i++)
{
vector<int> s;
for (int j = 0; j < n; j++)
{
int t = 0;
s.push_back(t);
}
c.push_back(s);
}
mul(a, b, c, 0, 0, 0, 0, n);
output(c, x1, y2);
}
system("pause");
}
void output(vector2 const &a,int x1,int y1)
{
for (int i = 0; i < x1; i++)
{
for (int j = 0; j < y1; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
}
void input(vector2 &a, int x1, int y1,int n)//补充的具体实现
{
vector<int> s;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (i < x1&&j < y1)
{
int t;
cin >> t;
s.push_back(t);
}
else
{
s.push_back(0);
}
}
a.push_back(s);
s.clear();
}
}
int padding (vector2&a, vector2 &b, int x1, int y1, int x2,int y2)//判断应该补充多少
{
int n = 6;//2的6次方已经极大
for (int i = 2; i <= n; i++)
{
int t = pow(2, i);
if (t >= x1)//判断n应该为多少
{
n = t;
break;
}
}
input(a, x1, y1, n);
input(b, x2, y2, n);
return n;
}
void mul(const vector2 a, const vector2 b, vector2 &c, int x, int y, int x1, int y1, int n)
{
if (n == 2)
{
n = n - 1;
int s[10];
s[0] = b[x1][y1 + n] - b[x1 + n][y1 + n];
s[1] = a[x][y] + a[x][y + n];
s[2] = a[x + n][y] + a[x + n][x + n];
s[3] = b[x1 + n][y1] - b[x1][y1];
s[4] = a[x][y] + a[x + n][y + n];
s[5] = b[x1][y1] + b[x1 + n][y1 + n];
s[6] = a[x][y + n] - a[x + n][y + n];
s[7] = b[x1 + n][y1] + b[x1 + n][y1 + n];
s[8] = a[x][y] - a[x + n][y];
s[9] = b[x1][y1] + b[x1][y1 + n];
int p[7];
p[0] = a[x][y] * s[0];
p[1] = s[1] * b[x1 + n][y1 + n];
p[2] = s[2] * b[x1][y1];
p[3] = s[3] * a[x + n][y + n];
p[4] = s[4] * s[5];
p[5] = s[6] * s[7];
p[6] = s[8] * s[9];
c[x][y1] += p[4] + p[3] - p[1] + p[5];
c[x][y1 + n] += p[0] + p[1];
c[x + n][y1] += p[2] + p[3];
c[x + n][y1 + n] += p[4] + p[0] - p[2] - p[6];
}
else
{
n = n / 2;
mul(a, b, c, x, y, x1, y1, n);
mul(a, b, c, x, y + n, x1 + n, y1, n);
mul(a, b, c, x, y, x1, y1 + n, n);
mul(a, b, c, x, y + n, x1 + n, y1 + n, n);
mul(a, b, c, x + n, y, x1, y1, n);
mul(a, b, c, x + n, y + n, x1 + n, y1, n);
mul(a, b, c, x + n, y, x1, y1 + n, n);
mul(a, b, c, x + n, y + n, x1 + n, y1 + n, n);
}
}
void main()
{
vector2 a, b, c;
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
if (y1 != x2)
{
cout << "error not *" << endl;
}
else
{
int n=padding(a, b, x1, y1, x2, y2);
for (int i = 0; i < n; i++)
{
vector<int> s;
for (int j = 0; j < n; j++)
{
int t = 0;
s.push_back(t);
}
c.push_back(s);
}
mul(a, b, c, 0, 0, 0, 0, n);
output(c, x1, y2);
}
system("pause");
}