突然恍然,无论是贪心算法还是动态规划,最重要的基础是基础排序。其次才是判断所求解是最优解还是次优解,其中背包问题确实能把两者的区别搞清楚。后续在看最小生成树的时候,发现Prim算法和Kruskal算法都是应用贪心算法的
Prim O(n^2)
#include<stdio.h> #include<string.h> int g[101][101],cost[101],flag[101],n,m,ans; void init(){ int i,j; scanf("%d",&n); for(i=1;i<=n;i++) for(j=1;j<=n;j++) scanf("%d",&g[i][j]); for(i=1;i<=n;i++) g[i][i]=2000000000; } void prim(){ int i,j,u,MIN; for(i=1;i<=n;i++) cost[i]=g[1][i]; flag[1]=1; for(j=2;j<=n;j++){ MIN=2000000000; for(i=1;i<=n;i++) if(flag[i]==0&&cost[i]<MIN){ MIN=cost[i]; u=i; } if(u>0){ flag[u]=1; ans+=MIN; for(i=1;i<=n;i++){ if(flag[i]==0&&cost[i]>g[u][i]) cost[i]=g[u][i]; } } } } void solve(){ prim(); printf("%d",ans); } int main(){ init(); solve(); return(0); }
kruskal
一般来说把Kruskal 的复杂度表述为O (ElogV )
用到并查集
#include<iostream>
using namespace std;
typedef struct node{
int v1,v2,len;
};
node e[100001];
int n,m,fa[100001],ans;
void qsort(int l,int r){
int x,i,j;
node temp;
i=l;
j=r;
x=e[(l+r)/2].len;
while(i<=j){
while(e[i].len<x)i++;
while(e[j].len>x)j--;
if(i<=j){
temp=e[i];e[i]=e[j];e[j]=temp;
i++;
j--;
}
}
if(l<j)qsort(l,j);
if(i<r)qsort(i,r);
}
int find(int x){
if(fa[x]==0)return(x);
fa[x]=find(fa[x]);
return(fa[x]);
}
void init(){
int i,j,k;
/*cin>>n>>m;
for(i=1;i<=m;i++)
cin>>e[i].v1>>e[i].v2>>e[i].len;*/
memset(fa,0,sizeof(fa));
cin>>n;
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
cin>>k;
if(i<j){
m++;
e[m].v1=i;
e[m].v2=j;
e[m].len=k;
}
}
}
qsort(1,m);
ans=0;
}
void solve(){
int k,i,f1,f2,total=0;
for(i=1;i<=m;i++){
if(total==n-1)break;
f1=find(e[i].v1);
f2=find(e[i].v2);
if(f1!=f2){
fa[f1]=f2;
ans+=e[i].len;
total++;
}
}
cout<<ans<<endl;
}
int main(){
init();
solve();
}