旧题复习{6}
1.樹形背包
洛谷P1273有線電視網==poj1155tele
//一個孩子一個分組,枚舉每個組選幾個(給每個孩子分配體積) //沙茶的輸出打錯了 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int N=3e3+5,INF=1e9; int read(){char c=getchar();int x=0,f=1;while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}return x*f; } int n,m,s,v,w; struct edge{int v,w,ne; }e[N<<1]; int h[N],cnt=0; void ins(int u,int v,int w){cnt++;e[cnt].v=v;e[cnt].w=w;e[cnt].ne=h[u];h[u]=cnt;cnt++;e[cnt].v=u;e[cnt].w=w;e[cnt].ne=h[v];h[v]=cnt; }int d[N][N],son[N]; void dfs(int u,int fa){if(u>=n-m+1) return;for(int j=1;j<=m;j++) d[u][j]=-INF;for(int i=h[u];i;i=e[i].ne){int v=e[i].v,w=e[i].w;if(v==fa) continue;dfs(v,u);son[u]+=son[v];for(int j=son[u];j>=1;j--){int t=min(j,son[v]);for(int k=1;k<=t;k++)d[u][j]=max(d[u][j],d[u][j-k]+d[v][k]-w);}} } int main(){n=read();m=read();for(int i=1;i<=n-m;i++){s=read();while(s--){v=read();w=read();ins(i,v,w);}}for(int i=n-m+1;i<=n;i++) d[i][1]=read(),son[i]=1;dfs(1,0);for(int i=m;i>=1;i--) if(d[1][i]>=0) {printf("%d",i);break;} }?
2.P2627 修剪草坪
狀態損失最小而不是得到最大,就可以單調隊列優化
最后n-k到n都可以作為答案
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int N=1e5+5; typedef long long ll; const ll INF=1e18; inline int read(){char c=getchar();int x=0,f=1;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}return x*f; } int n,k,e; int q[N],head=1,tail=0; ll f[N],sum; int main(){n=read();k=read();q[tail++]=0;for(int i=1;i<=n;i++){e=read(); sum+=e;while(head<=tail&&i-q[head]-1>k) head++;f[i]=f[q[head]]+e;while(head<=tail&&f[q[tail]]>=f[i]) tail--;q[++tail]=i;// printf("f %d %d\n",i,f[i]); }ll mn=INF;for(int i=n-k;i<=n;i++) mn=min(mn,f[i]);printf("%lld",sum-mn); }?
?
3.poj1742coins
多重背包可行性 F[I][J]前i個湊成j還剩幾個i
注意0是可行的
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=105,M=1e5+5; inline int read(){char c=getchar();int x=0,f=1;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}return x*f; } int n,m,w[N],c[N]; int f[M]; void dp(){memset(f,-1,sizeof(f));f[0]=0;for(int i=1;i<=n;i++){for(int j=0;j<=m;j++){if(f[j]>=0) f[j]=c[i]; else f[j]=-1;}for(int j=0;j<=m-w[i];j++) if(f[j]>0) f[j+w[i]]=max(f[j+w[i]],f[j]-1);} } int main(){while(scanf("%d%d",&n,&m)!=EOF&&n+m){for(int i=1;i<=n;i++) w[i]=read();for(int i=1;i<=n;i++) c[i]=read();dp();int ans=0;for(int j=1;j<=m;j++) if(f[j]>=0) ans++;//,printf("f %d\n",j);printf("%d\n",ans);} }?
?
4.洛谷P2423雙塔==vijos
注意除了-1高度為0也是不可行
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=105,M=2005; inline int read(){char c=getchar();int x=0,f=1;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}return x*f; } int n,h[N],sum=0; int f[2][M]; void dp(){int now=1;memset(f,-1,sizeof(f));f[0][0]=0;for(int i=1;i<=n;i++,now^=1){int pre=now^1;for(int j=0;j<=sum;j++){f[now][j]=f[pre][j];if(j-h[i]>=0&&f[pre][j-h[i]]!=-1) f[now][j]=max(f[now][j],f[pre][j-h[i]]+h[i]);if(f[pre][j+h[i]]!=-1) f[now][j]=max(f[now][j],f[pre][j+h[i]]);if(h[i]-j>0&&f[pre][h[i]-j]!=-1) f[now][j]=max(f[now][j],f[pre][h[i]-j]+j); }} } int main(){n=read();for(int i=1;i<=n;i++) h[i]=read(),sum+=h[i];dp();if(f[n&1][0]<=0) puts("Impossible");else printf("%d",f[n&1][0]); }?
5.LCIS
注意滾動數組的應用
mx就應該邊推內層邊取mx,因為mx取得位置要<j
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=505; inline int read(){char c=getchar();int x=0,f=1;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}return x*f; } int n,m,a[N],b[N]; int f[N]; void dp(){memset(f,0,sizeof(f));for(int i=1;i<=n;i++){int mx=0;for(int j=1;j<=m;j++){if(a[i]>b[j]) mx=max(mx,f[j]);if(a[i]==b[j]) f[j]=mx+1;}} } int main(){int T=read();while(T--){n=read(); for(int i=1;i<=n;i++) a[i]=read();m=read(); for(int i=1;i<=m;i++) b[i]=read();dp();int ans=0;for(int i=1;i<=m;i++) ans=max(ans,f[i]);printf("%d\n",ans);} }?
?
6.poj3636
二維偏序問題,注意排序時相等怎么辦
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=2e4+5,INF=1e9; inline int read(){char c=getchar();int x=0,f=1;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}return x*f; } int n; struct doll{int w,h;bool operator <(const doll &r)const{if(w==r.w) return h>r.h;return w<r.w;} }d[N]; int f[N],g[N],a[N]; inline bool cmp(int a,int b){return a>b;} int dp(){int ans=0;for(int i=1;i<=n;i++) g[i]=-INF,a[i]=d[i].h;for(int i=1;i<=n;i++){int k=upper_bound(g+1,g+1+n,a[i],cmp)-g;f[i]=k;g[k]=a[i];ans=max(ans,f[i]);//printf("f %d %d\n",i,f[i]); }return ans; } int main(){int T=read();while(T--){n=read();for(int i=1;i<=n;i++) d[i].w=read(),d[i].h=read();sort(d+1,d+1+n);printf("%d\n",dp());} }?
總結
- 上一篇: sirikit
- 下一篇: 利用 Chef 在 Red Hat En