【专题】 动态规划
递推类
hdu 2084 数塔 简单从上往下递推
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<queue> 6 #include<cmath> 7 #include<cstring> 8 using namespace std; 9 #define rg register 10 #define ll long long 11 const int N=100+5; 12 int n,ans=0,f[N][N],mp[N][N]; 13 template<class t>void rd(t &x) 14 { 15 x=0;int w=0;char ch=0; 16 while(!isdigit(ch)) w|=ch=='-',ch=getchar(); 17 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 18 x=w?-x:x; 19 } 20 21 int main() 22 { 23 int T;rd(T); 24 while(T--) 25 { 26 ans=0; 27 memset(f,0,sizeof(f)); 28 memset(mp,-1,sizeof(mp)); 29 rd(n); 30 for(rg int i=1;i<=n;++i) 31 for(rg int j=1;j<=i;++j) rd(mp[i][j]); 32 f[1][1]=mp[1][1]; 33 for(rg int i=2;i<=n;++i) 34 for(rg int j=1;j<=i;++j) 35 f[i][j]=max(f[i][j],max(f[i-1][j]+mp[i][j],f[i-1][j-1]+mp[i][j])); 36 for(rg int i=1;i<=n;++i) ans=max(ans,f[n][i]); 37 printf("%d\n",ans); 38 } 39 return 0; 40 }
hdu 2018 母牛的故事 简单递推计数 和斐波那契差不多emmm
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<queue> 6 #include<cmath> 7 #include<cstring> 8 using namespace std; 9 #define rg register 10 #define ll long long 11 const int N=60; 12 int n,f[N]; 13 template<class t>void rd(t &x) 14 { 15 x=0;int w=0;char ch=0; 16 while(!isdigit(ch)) w|=ch=='-',ch=getchar(); 17 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 18 x=w?-x:x; 19 } 20 21 int main() 22 { 23 f[1]=1,f[2]=2,f[3]=3; 24 for(rg int i=4;i<=55;++i) f[i]=f[i-3]+f[i-1]; 25 while(scanf("%d",&n)==1&&n) 26 { 27 printf("%d\n",f[n]); 28 } 29 return 0; 30 }
hdu 2044 一只小蜜蜂... 同上 要记得开long long QAQ
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<queue> 6 #include<cmath> 7 #include<cstring> 8 using namespace std; 9 #define rg register 10 #define ll long long 11 const int N=60; 12 ll n,f[100],a,b; 13 template<class t>void rd(t &x) 14 { 15 x=0;int w=0;char ch=0; 16 while(!isdigit(ch)) w|=ch=='-',ch=getchar(); 17 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 18 x=w?-x:x; 19 } 20 21 int main() 22 { 23 memset(f,0,sizeof(f)); 24 f[1]=1; 25 for(ll i=2;i<=60;++i) f[i]=f[i-1]+f[i-2]; 26 rd(n); 27 for(ll i=1;i<=n;++i) 28 { 29 rd(a),rd(b); 30 printf("%lld\n",f[b-a+1]); 31 } 32 33 return 0; 34 }
CodeForces - 429B Working out
大意:有小A和小B 小A从[1,1]出发到[n,m] 小B从[n,1]出发到[1,m] 两个人必须在达各自终点前相遇一次,并且相遇那个点的值不能取 求这样子走完后小A和小B共同获得的最大价值
看翻译的时候不小心看到了思路 哭泣QAQ
先算出从四个点出发到各个点的最大价值 然后枚举可能相遇的点 因为要在达各自终点前相遇一次所以相遇点的i和j要从2开始枚举(QAQ没考虑到这个到test23就挂了)
相遇时只有这两种可能(丑陋的图)
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<queue> 6 #include<cmath> 7 #include<cstring> 8 using namespace std; 9 #define rg register 10 #define ll long long 11 const int N=1005; 12 int n,m,ans=0,f[5][N][N],mp[N][N]; 13 template<class t>void rd(t &x) 14 { 15 x=0;int w=0;char ch=0; 16 while(!isdigit(ch)) w|=ch=='-',ch=getchar(); 17 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 18 x=w?-x:x; 19 } 20 21 int main() 22 { 23 memset(f,0,sizeof(f)); 24 rd(n),rd(m); 25 for(rg int i=1;i<=n;++i) 26 for(rg int j=1;j<=m;++j) rd(mp[i][j]); 27 for(rg int i=1;i<=n;++i) 28 { 29 for(rg int j=1;j<=m;++j) 30 f[1][i][j]=max(f[1][i][j],max(f[1][i-1][j],f[1][i][j-1])+mp[i][j]);//[1,1]-[n,m] 31 for(rg int j=m;j>=1;--j) 32 f[2][i][j]=max(f[2][i][j],max(f[2][i-1][j],f[2][i][j+1])+mp[i][j]);//[1,m]-[n,1] 33 } 34 for(rg int i=n;i>=1;--i) 35 { 36 for(rg int j=1;j<=m;++j) 37 f[3][i][j]=max(f[3][i][j],max(f[3][i+1][j],f[3][i][j-1])+mp[i][j]);//[n,1]-[1,m] 38 for(rg int j=m;j>=1;--j) 39 f[4][i][j]=max(f[4][i][j],max(f[4][i+1][j],f[4][i][j+1])+mp[i][j]);//[n,m]-[1,1] 40 } 41 for(rg int i=2;i<n;++i) 42 for(rg int j=2;j<m;++j) 43 ans=max(ans,max(f[1][i-1][j]+f[4][i+1][j]+f[2][i][j+1]+f[3][i][j-1],f[3][i+1][j]+f[2][i-1][j]+f[4][i][j+1]+f[1][i][j-1])); 44 printf("%d",ans); 45 return 0; 46 }
【UVa 10328】Coin Toss [动态规划 递推][高精度]
树形dp
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1500+5; 4 5 int n,f[N][2]; 6 int cnt=0,head[N<<1]; 7 int read() 8 { 9 int x=0,w=0;char ch=0; 10 while(!isdigit(ch)) {w|=ch=='-';ch=getchar();} 11 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 12 return w?-x:x; 13 } 14 struct edge 15 { 16 int v,nxt; 17 }e[N<<1]; 18 void add(int u,int v) 19 { 20 e[++cnt].v=v; 21 e[cnt].nxt=head[u]; 22 head[u]=cnt; 23 } 24 25 void dp(int u,int fa) 26 { 27 f[u][0]=0,f[u][1]=1; 28 for(int i=head[u];i!=0;i=e[i].nxt) 29 { 30 int v=e[i].v; 31 if(v==fa) continue; 32 dp(v,u); 33 f[u][0]+=f[v][1]; 34 f[u][1]+=min(f[v][0],f[v][1]); 35 } 36 } 37 38 int main() 39 { 40 while(scanf("%d",&n)!=EOF) 41 { 42 memset(head,0,sizeof(head));cnt=0; 43 for(int i=0;i<n;i++) 44 { 45 int x,k; 46 scanf("%d:(%d)",&x,&k); 47 for(int j=0;j<k;j++) 48 { 49 int a=read(); 50 add(x,a);add(a,x); 51 } 52 } 53 dp(0,-1); 54 printf("%d\n",min(f[0][0],f[0][1])); 55 } 56 return 0; 57 }
没有上司的舞会 树形dp
longest 求树的直径
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1005; 4 const int inf=0x3f3f3f; 5 int n,f[N][2],ans=0; 6 int cnt=0,head[N<<1]; 7 int read() 8 { 9 int x=0,w=0;char ch=0; 10 while(!isdigit(ch)) {w|=ch=='-';ch=getchar();} 11 while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); 12 return w?-x:x; 13 } 14 struct edge 15 { 16 int v,nxt,w; 17 }e[N]; 18 void add(int u,int v,int w) 19 { 20 e[++cnt].v=v; 21 e[cnt].w=w; 22 e[cnt].nxt=head[u]; 23 head[u]=cnt; 24 } 25 26 void dp(int u,int fa) 27 { 28 f[u][1]=0,f[u][2]=0; 29 for(int i=head[u];i;i=e[i].nxt) 30 { 31 int w=e[i].w,v=e[i].v; 32 if(v==fa) continue; 33 dp(v,u);//搜儿子 34 int dis=f[v][1]+w; 35 if(dis>f[u][1]) 36 { 37 f[u][2]=f[u][1]; 38 f[u][1]=dis; 39 } 40 else if(dis>f[u][2]) 41 { 42 f[u][2]=dis; 43 } 44 ans=max(ans,f[u][1]+f[u][2]); 45 } 46 } 47 48 int main() 49 { 50 memset(head,0,sizeof(head)); 51 n=read(); 52 for(int i=1;i<n;i++) 53 { 54 int u=read(),v=read(),w=read(); 55 add(u,v,w);add(v,u,w); 56 } 57 dp(1,0); 58 printf("%d",ans); 59 return 0; 60 }