1.ROSE矩阵
实现:
使用算法2
分析: 每半圈元素值的增长规律变换一次
设增量为t,每半圈变换一次t <— -t .
设矩阵边长为i,每半圈的元素个数是2*(i-1)个,hc为记数变量,则1≤hc<=2i-1,前1/4圈是1≤hc<=i-1,后1/4是i≤hc<=2i-2,若hc%i==0,则前1/4圈结果为0,后1/4结果为1,可表示为:index <— hc/i, hc <— hc+1。
计算模型:
设s[1]为矩阵行下标,s[0]为矩阵列下标。s数组下标为index。
t为下标增量,初值为-1,矩阵元素k∈[1,n*n].
1.index<- hc/i+1
2.hc<- hc+1
3.hc∈[1,2*i-1]
4.s[index]<-s[index]+t
5.a[s[1],s[0]]<- k , k<- k+1
6.当hc>2*i-1,i<- i-1 ,t<- -t
代码:
void rose(int n)
{
int s[2];
int a[n][n];
int k=1,i=n,t=1;
s[0]=-1,s[1]=0;
while(k<=n*n)
{
for(int hc=1;hc<=2*i-1;++hc)
{
int index=hc/(i+1);
s[index]+=t;
a[s[1]][s[0]]=k;
++k;
}
i--;
t=-t;
}
for(int i=0;i<n;++i)
{
for(int j=0;j<n;++j)
{
cout<<a[i][j]<<"\t";
}
cout<<endl;
}
}
2.迷宫
最优路径?
可以使用栈或队列完成。
定义:
int M
[
10
]
[
10
]
[10][10]
[10][10]={
1,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,0,0,0,0,1,
1,0,1,1,1,1,0,1,0,1,
1,0,0,0,0,1,0,1,0,1,
1,0,1,0,0,0,0,1,0,1,
1,0,1,0,1,1,0,1,0,1,
1,0,1,0,0,0,0,1,1,1,
1,0,1,0,0,1,0,0,0,1,
1,0,1,1,1,1,1,1,0,1,
1,1,1,1,1,1,1,1,1,1,} ;
//状态定义 :
// M
[
x
]
[
y
]
[x][y]
[x][y]为0:通路 ,为1:墙 , 为2:死路 , 为3:已走过
int fx[]={-1,1,0,0};
int fy[]={0,0,-1,1};
typedef struct p
{
int x,y;
struct p* next;
}point;
1).若使用栈:
主要代码:
void bfs()
{
stack<point*>s;
point *head=new point,*p;
int x=1,y=1;
head->x=x;
head->y=y;
head->next=NULL;
M[x][y]=3;
s.push(head);
int flag=0;
while(!s.empty() )
{
p=s.top();
s.pop();
//cout<<"front:"<<p->x<<" "<<p->y<<endl;
for(int i=0;i<4;++i)
{
y=p->y+fy[i];
x=p->x+fx[i];
if(M[x][y]==0)
{
//cout<<x<<" "<<y<<endl;
M[x][y]=3;
point * newp=new point;
newp->x=x;
newp->y=y;
newp->next=p;
s.push(newp);
if(x==8 && y==8)
{
flag=1;
break;
}
}
}
if(flag)break;
}
p=s.top();
while(p)
{
cout<<"("<<p->x<<","<<p->y<<")"<<" ";
p=p->next;
}
}
具体实现:
使用栈可以完成查找,但因其后入先出的特性,在程序实现中,优先对左上方的节点进行查找,针对此迷宫而言会产生一些不必要的路径。
所以若想最短时间得到最优路径可以使用队列。
2).队列实现:队列由于其先入先出的特点,每次都对右下方的点进行率先遍历,故更容易找到最优路径。
使用链表存储。
主要代码实现:
void bfs()
{
m[x][y]=3;
p=new po;
p->x=x;
p->y=y;
p->pre=NULL;
q.push(p);
while(!q.empty() )
{
po * p1=q.front();
q.pop();
for(int i=0;i<4;i++)
{
po* pnew=new po;
pnew->pre=NULL;
pnew->x =p1->x + fx[i];
pnew->y = p1->y+ fy[i];
if(m[pnew->x][pnew->y] ==0 )
{
m[pnew->x][pnew->y]=3;
pnew->pre=p1;
q.push(pnew);
}
if(pnew->x==8 && pnew->y==8)
return;
}
}
}
实现:
使用队列来实现,其时间为使用栈实现的一半左右。
3.三壶问题
BFS思想 穷举+回溯.
代码实现:
逐步模拟三个壶的倒水状态
typedef struct node
{
int x,y,z;
struct node * pre;
}node;
queue<node*>q;
node *p2;
node *p3;
set<int> cha;
bool is(node *p)
{
if(p->x==4||p->y==4||p->z==4)
return true;
else return false;
}
void out(node *p)
{
cout<<"("<<p->x<<","<<p->y<<","<<p->z<<")"<<endl;
}
void BFS()
{
node *p=new node;
p->x=8;p->y=0;p->z=0;
p->pre=NULL;
q.push(p);
while(!q.empty())
{
node *p1=q.front();
if(is(p1)) return;
int x=p1->x;
int y=p1->y;
int z=p1->z;
q.pop();
if(cha.find(x*100+y*10+z)!=cha.end()) //没有任何一组状态使用此公式得到的计算结果是相同的,故用此来判别状态是否已被遍历
continue;
else cha.insert(x*100+y*10+z);
if(x>0&&y<5)
{
p3=new node;
if(x+y>5)
{
p3->x=x+y-5;
p3->y=5;
}
else
{
p3->x=0;
p3->y=x+y;
}
p3->z=z;
p3->pre=p1;
q.push(p3);
if(is(p3)) return;
}
if(x>0&&z<3)
{
p3=new node;
if(x+z>3)
{
p3->x=x+z-3;
p3->z=3;
}
else
{
p3->x=0;
p3->z=x+z;
}
p3->y=y;
p3->pre=p1;
q.push(p3);
if(is(p3)) return;
}
if(y>0)
{
p3=new node;
p3->x=x+y;
p3->y=0;
p3->z=z;
p3->pre=p1;
q.push(p3);
if(is(p3)) return;
}
if(z>0)
{
p3=new node;
p3->x=x+z;
p3->z=0;
p3->y=y;
p3->pre=p1;
q.push(p3);
if(is(p3)) return;
}
if(y>0&&z<3)
{
p3=new node;
if(y+z>3)
{
p3->y=y+z-3;
p3->z=3;
}
else
{
p3->y=0;
p3->z=y+z;
}
p3->x=x;
p3->pre=p1;
q.push(p3);
if(is(p3)) return;
}
if(z>0&&y<5)
{
p3=new node;
if(y+z>5)
{
p3->z=y+z-5;
p3->y=5;
}
else
{
p3->z=0;
p3->y=y+z;
}
p3->x=x;
p3->pre=p1;
q.push(p3);
if(is(p3)) return;
}
}
}
4.蛮力匹配
有A B两个字符串 ,长度为n和m
则其最差情况下:首先让A从第一个字符与B的各个字符进行比较,耗时m,A中共n个字符
耗时:O((n-m-1)*m)
5.相当于全排列,则共需 T(n)=O( (n-1)! )时间
6.经计算:15!=1307674368000
16!=20922789888000
18!=6402373705728000
19!=121645100408832000
1小时 运算:3.6* 1 0 13 10^{13} 1013次 16个城市
24小时 运算8.64* 1 0 14 10^{14} 1014次 17个城市
1年运算3.1536* 1 0 17 10^{17} 1017次 19个城市
100年运算3.1536* 1 0 19 10^{19} 1019次 20个城市
- BFS时间复杂度分析
使用邻接表完成
对于 G 令 vexnum=n 即节点数量为n 对于邻接表:共e条边
则其所需时间共分为两部分,n个节点需要O(n)的复杂度,
而邻接表需O(e)的复杂度~ 总时间复杂度为O(n+e).
8.背包问题
1)时间复杂度
单纯通过穷举法,则:对于n个物品,会有 2 n − 1 2^{n-1} 2n−1种解 时间复杂度为 O ( 2 n ) O(2^{n}) O(2n)
2)改进
动规
int main()
{
int N, V;
cin >> N >> V;
vector<int> v(N + 1), w(N + 1), f(V + 1);
for(int i = 1; i <= N; ++i)
cin >> v[i] >> w[i];
for(int i = 1; i <= N; ++i)
for(int j = V; j >= v[i]; --j)
f[j] = max(f[j], f[j - v[i]] + w[i]);
cout << *max_element(f.begin(), f.end());
return 0;
}
时间复杂度: O ( N ∗ V ) O(N*V) O(N∗V)
贪心
对物品的: 价值/物品体积 进行排序,逐个判断其体积是否能被装下
int G()
{
float temp=0;
float result=0;
float c1=8;
for(int i=0;i<4;i++)
{
for(i=0;i<4;i++)
{
if(temp<sortBest[i])
temp=sortBest[i];
}
//cout<<"max(sortBest)="<<temp<<endl;
for(i=0;i<4;i++)
{
if (temp==sortBest[i])
sortBest[i]=0;
if (w[i]<=c1)
result=result+v[i];
c1=c1-w[i];
}
}
时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)