最后一战の板子

谜之soul_北冥X

2020-12-03 20:06:21

Personal

# ~~AFO前的挣扎~~ # DP ## 01背包 ```cpp //无优化 for(int i=1;i<=n;i++) { for(int c=0;c<=m;c++) { f[i][c]=f[i-1][c]; if(c>=w[i]) f[i][c]=max(f[i][c],f[i-1][c-w[i]]+v[i]); } } //一位数组优化 for(int i=1;i<=n;i++) { for(int c=m;c>=0;c--) { if(c>=w[i]) f[c]=max(f[c],f[c-w[i]]+v[i]); } } //常数优化 for(int i=1;i<=n;i++) { sumw+=w[i]; bound=max(m-sumw,w[i]); for(int c=m;c>=bound;c--) { if(c>=w[i]) f[c]=max(f[c],f[c-w[i]]+v[i]); } } ``` ## 完全背包 ```cpp for(int i=1;i<=n;i++) { for(int c=0;c<=m;c++) { if(c>=w[i]) f[c]=max(f[c],f[c-w[i]]+v[i]); } } ``` ## 多重背包 ```cpp for(int i=1;i<=n;i++) { if(w[i]*a[i]>m) { for(int c=0;c<=m;c++) { if(c>=w[i]) f[c]=max(f[c],f[c-w[i]]+v[i]); } } else { k=1;amount=a[i]; while(k<amount) { for(int c=k*w[i];c>=0;c--) { if(c>=w[i]) f[c]=max(f[c],f[c-w[i]]+k*v[i]); } amount-=k; k<<=1; } for(int c=amount*w[i];c>=0;c--) { f[c]=max(f[c],f[c-w[i]]+amount*v[i]); } } } ``` ## 带有附件的01背包 ```cpp for(int i=1;i<=m;i++){// read int a,b,c; a=read(); b=read(); c=read(); if(c==0){ //无附件 zw[i]=a; zv[i]=a*b; } else{ //有附件 fw[c][0]++; fw[c][fw[c][0]]=a; fv[c][fw[c][0]]=a*b; } } for(int i=1;i<=m;i++){ for(int j=n;j>=zw[i]&&zw[i]!=0;j--){ dp[j] = max(dp[j],dp[j-zw[i]]+zv[i]); if(j >= zw[i]+fw[i][1]) dp[j] = max(dp[j],dp[j-zw[i]-fw[i][1]]+zv[i]+fv[i][1]); if(j >= zw[i]+fw[i][2]) dp[j] = max(dp[j],dp[j-zw[i]-fw[i][2]]+zv[i]+fv[i][2]); if(j >= zw[i]+fw[i][1]+fw[i][2]) dp[j] = max(dp[j],dp[j-zw[i]-fw[i][1]-fw[i][2]]+zv[i]+fv[i][2]+fv[i][1]); } } ``` ## 最长上升子序列(n log n) ```cpp dp[1]=h[1]; for(int i=2;i<=cnt;i++) { if(dp[len]>=h[i]) dp[++len]=h[i]; else{ int a=upper_bound(dp+1,dp+1+len,h[i])-dp; dp[a]=h[i]; } ``` # 图论 ## 存图 ```cpp //邻接矩阵(有向图) for(int i=1;i<=m;i++){ int u,v,w; cin>>u>>v>>w; mapp[u][v]=w; } //边集数组(有向图) for(int i=1;i<=m;i++){ int u,v,w; cin>>u>>v>>w; e[i].u=u; e[i].v=v; e[i].dis=w; } //链式前向星 (有向图) void addedge(int u,int v,int w){ e[cnt].to=v; e[cnt].dis=w; e[cnt].next=h[u]; h[u]=++cnt; } ``` ## 最短路 ```cpp //Floyd for(int k=0;k<n;k++){ //k为中间节点 for(int i=0;i<n;i++) //i为起点 for(int j=0;j<n;j++) //j为终点 if(i!=k&&i!=j&&k!=j) if(arr[i][k]+arr[k][j]<arr[i][j]) arr[i][j]=arr[i][k]+arr[k][j]; } //Dijkstra void dijkstra(int k){ dis[k]=0; q.push((node){0,k}); while(!q.empty()){ node tp=q.top(); int x=tp.pos; int d=tp.dis; q.pop(); if(vis[x]==1) continue; vis[x]=1; for(int i=h[x];i;i=e[i].next){ int y=e[i].to; if(dis[y]>dis[x]+e[i].dis){ dis[y]=dis[x]+e[i].dis; q.push((node){dis[y],y}); } } } } ``` ## 最小生成树 ```cpp //kruskal int find(int x){ while(x!=f[x]) x=f[x]=f[f[x]]; return x; } bool cmp(edge a,edge b){ return a.w<b.w; } void kruskal(){ for(int i=1;i<=1001;i++) f[i]=i; int cnt=0; sort(e+1,e+1+m,cmp); for(int i=1;i<=m;i++){ int ev,eu; ev=find(e[i].v); eu=find(e[i].u); if(ev==eu) continue; tot+=e[i].w; f[eu]=ev; if(++cnt==n-1) break; } return; } //prim priority_queue<node> myq; void pulimu(){ int cc=0; dis[1]=0; myq.push((node){0,1}); while(!myq.empty()&&cc<n){ node temp=myq.top(); myq.pop(); int x=temp.pos; int d=temp.dis; if(vis[x]==1) continue; vis[x]=1; cc++; ans+=d; for(int i=h[x];i;i=e[i].next){ if(dis[e[i].to]>e[i].dis){ dis[e[i].to]=e[i].dis; myq.push((node){dis[e[i].to],e[i].to}); } } } return; } ```