第六周 6.21-6.27
6.21
LIS有nlgn的算法。纯学dp。
1 # include <iostream> 2 # include <cstdio> 3 # include <algorithm> 4 using namespace std; 5 int num[5005],d[5005]; 6 7 int main(void) 8 { 9 int n; cin>>n; 10 for(int i=0;i<n;i++) scanf("%d",num+i); 11 for(int i=0;i<n;i++) 12 { 13 d[i]=1; 14 for(int j=0;j<i;j++) 15 if(num[j]<=num[i]) d[i]=max(d[i],d[j]+1); 16 } 17 int ans=0; 18 for(int i=0;i<n;i++) ans=max(ans,d[i]); 19 printf("%d\n",ans); 20 return 0; 21 }
紫薯题。
1 # include <iostream> 2 # include <cstdio> 3 # include <algorithm> 4 using namespace std; 5 int dp[1005]; 6 7 struct node 8 { 9 int a,b; 10 }edge[1005]; 11 12 bool cmp(node x,node y) 13 { 14 if(x.a!=y.a) return x.a<y.a; 15 else return x.b<y.b; 16 } 17 18 int main(void) 19 { 20 int N;cin>>N; 21 while(N--) 22 { 23 int n;scanf("%d",&n); 24 for(int i=0;i<n;i++) 25 { 26 scanf("%d%d",&edge[i].a,&edge[i].b); 27 if(edge[i].a<edge[i].b) 28 { 29 int t=edge[i].a; 30 edge[i].a=edge[i].b; 31 edge[i].b=t; 32 } 33 } 34 sort(edge,edge+n,cmp); 35 for(int i=0;i<n;i++) 36 { 37 dp[i]=1; 38 for(int j=0;j<i;j++) 39 if(edge[j].a<edge[i].a&&edge[j].b<edge[i].b) dp[i]=max(dp[i],dp[j]+1); 40 } 41 int ans=0; 42 for(int i=0;i<n;i++) ans=max(ans,dp[i]); 43 printf("%d\n",ans); 44 } 45 return 0; 46 }
6.22
UVA 103 Stacking Boxes
升级版的n维矩形。打印一个路径就好。然而数据太亲民。
1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 using namespace std; 6 int k,n,dp[30],G[30][30]; 7 8 struct BOX 9 { 10 int no,edge[10]; 11 }box[30]; 12 13 bool cmp(BOX a,BOX b) 14 { 15 for(int i=0;i<n;i++) 16 if(a.edge[i]!=b.edge[i]) return a.edge[i]<b.edge[i]; 17 return a.edge[n-1]<b.edge[n-1]; 18 } 19 20 void ans_print(int pos) 21 { 22 if(dp[pos]==1) printf("%d",box[pos].no); 23 else 24 { 25 for(int i=0;i<pos;i++) 26 if(G[i][pos]&&dp[i]==dp[pos]-1) 27 { 28 ans_print(i); 29 break; 30 } 31 printf(" %d",box[pos].no); 32 } 33 return; 34 } 35 36 int main(void) 37 { 38 while((scanf("%d%d",&k,&n))!=EOF) 39 { 40 memset(G,0,sizeof(G)); 41 for(int i=0;i<k;i++) 42 { 43 for(int j=0;j<n;j++) 44 scanf("%d",&box[i].edge[j]); 45 box[i].no=i+1; 46 sort(box[i].edge,box[i].edge+n); 47 } 48 sort(box,box+k,cmp); 49 for(int i=0;i<k;i++) 50 { 51 dp[i]=1; 52 for(int j=0;j<i;j++) 53 { 54 int ok=1; 55 for(int t=0;t<n;t++) 56 if(box[j].edge[t]>=box[i].edge[t]) {ok=0;break;} 57 if(ok) {G[j][i]=1; dp[i]=max(dp[i],dp[j]+1);} 58 } 59 } 60 int ans=0,pos; 61 for(int i=0;i<k;i++) if(dp[i]>ans) {ans=dp[i]; pos=i;} 62 printf("%d\n",ans); 63 ans_print(pos); 64 printf("\n"); 65 } 66 return 0; 67 }
6.23
发觉自己对dp的理解就有问题。紫薯啃的不明白。
文章也难找到合适的。
有的过于抽象。实例又容易固化思维。
稍微改了下就不会了。只能说没领会。
往上往下dp。
1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 using namespace std; 6 int n,x,y,num[26][26],d1[26][26],d2[26][26]; 7 8 int dp1(int i,int j) 9 { 10 if(d1[i][j]>=0) return d1[i][j]; 11 return d1[i][j]= ( (i==n)? num[i][j] : ( max(dp1(i+1,j),dp1(i+1,j+1))+num[i][j] ) ); 12 } 13 14 int dp2(int i,int j) 15 { 16 if(d2[i][j]>=0) return d2[i][j]; 17 if(i==1) return d2[i][j]=num[i][j]; 18 int ans=num[i][j]+dp2(i-1,j); 19 if(j-1>0) ans=max(ans,num[i][j]+dp2(i-1,j-1)); 20 return ans; 21 } 22 23 int main(void) 24 { 25 cin>>n; 26 memset(d1,-1,sizeof(d1)); 27 memset(d2,-1,sizeof(d2)); 28 for(int i=1;i<=n;i++) 29 for(int j=1;j<=i;j++) 30 scanf("%d",&num[i][j]); 31 scanf("%d%d",&x,&y); 32 printf("%d\n",dp1(x,y)+dp2(x,y)-num[x][y]); 33 return 0; 34 }
题目没什么。代码丑。
1 # include <iostream> 2 # include <cstdio> 3 # include <algorithm> 4 using namespace std; 5 # define X(i) (i/c+((i%c)?1:0)) 6 # define Y(i) ((i%c)?(i%c):c) 7 # define ID(i,j) ((i-1)*c+j) 8 int dp[10001],map[10001]; 9 10 struct node 11 { 12 int id,h; 13 } G[10001]; 14 15 bool cmp(node a,node b) 16 { 17 return a.h>b.h; 18 } 19 20 int main(void) 21 { 22 int r,c; cin>>r>>c; 23 for(int i=1;i<=r*c;i++) 24 { 25 scanf("%d",&G[i].h); 26 G[i].id=i; 27 } 28 sort(G+1,G+r*c+1,cmp); 29 for(int i=1;i<=r*c;i++) map[G[i].id]=i; 30 int ans=0; 31 for(int i=1;i<=r*c;i++) 32 { 33 int no=G[i].id,x=X(no),y=Y(no),H=G[i].h; 34 dp[no]=1; 35 if(x>1&&G[map[ID(x-1,y)]].h>H) dp[no]=max(dp[no],dp[G[map[ID(x-1,y)]].id]+1); 36 if(y>1&&G[map[ID(x,y-1)]].h>H) dp[no]=max(dp[no],dp[G[map[ID(x,y-1)]].id]+1); 37 if(x<r&&G[map[ID(x+1,y)]].h>H) dp[no]=max(dp[no],dp[G[map[ID(x+1,y)]].id]+1); 38 if(y<c&&G[map[ID(x,y+1)]].h>H) dp[no]=max(dp[no],dp[G[map[ID(x,y+1)]].id]+1); 39 ans=max(ans,dp[no]); 40 } 41 printf("%d\n",ans); 42 return 0; 43 }
6.24
HDU 1231 最大连续子序列
1 # include <iostream> 2 # include <cstdio> 3 using namespace std; 4 int num[10005],dp[10005],head[10005]; 5 6 int main(void) 7 { 8 int K; 9 while((scanf("%d",&K))!=EOF&&K) 10 { 11 for(int i=0;i<K;i++) 12 scanf("%d",num+i); 13 for(int i=0;i<K;i++) 14 if(i&&dp[i-1]>0) {dp[i]=dp[i-1]+num[i];head[i]=head[i-1];} 15 else {dp[i]=num[i];head[i]=num[i];} 16 int sum=-1,pos; 17 for(int i=0;i<K;i++) 18 if(dp[i]>sum) {sum=dp[i];pos=i;} 19 if(sum<0) printf("0 %d %d\n",num[0],num[K-1]); 20 else printf("%d %d %d\n",sum,head[pos],num[pos]); 21 } 22 return 0; 23 }
最长公共子序列 LCS
想不出来阿阿阿阿阿阿阿阿阿阿阿。
1 # include <iostream> 2 # include <cstdio> 3 # include <algorithm> 4 # include <cstring> 5 using namespace std; 6 char a[1005],b[1005]; 7 int F[1005][1005]; 8 9 int dp(int i,int j) 10 { 11 if(F[i][j]>=0) return F[i][j]; 12 if(i==0||j==0) return F[i][j]=0; 13 if(a[i]==b[j]) return F[i][j]=dp(i-1,j-1)+1; 14 return F[i][j]=max(dp(i,j-1),dp(i-1,j)); 15 } 16 17 int main(void) 18 { 19 int N;cin>>N; 20 while(N--) 21 { 22 memset(F,-1,sizeof(F)); 23 scanf("%s %s",a+1,b+1); 24 printf("%d\n",dp(strlen(a+1),strlen(b+1))); 25 } 26 return 0; 27 }
POJ 1050 To the Max
二维最大连续子列。
枚举了列的范围。在行求最大连续子列。
1 # include <iostream> 2 # include <cstdio> 3 # include <algorithm> 4 using namespace std; 5 int sum[105][105]={0},dp[105][105][105]; 6 7 int main(void) 8 { 9 int N; 10 while(cin>>N) 11 { 12 for(int i=1;i<=N;i++) 13 for(int j=1;j<=N;j++) 14 { 15 int x; scanf("%d",&x); 16 sum[i][j]=x; 17 if(j) sum[i][j]+=sum[i][j-1]; 18 } 19 int ans=-2147483647; 20 for(int i=1;i<=N;i++) 21 for(int j=i;j<=N;j++) 22 for(int k=1;k<=N;k++) 23 { 24 if(i&&dp[i][j][k-1]>0) dp[i][j][k]=dp[i][j][k-1]+sum[k][j]-sum[k][i-1]; 25 else dp[i][j][k]=sum[k][j]-sum[k][i-1]; 26 ans=max(ans,dp[i][j][k]); 27 } 28 printf("%d\n",ans); 29 } 30 return 0; 31 }
6.25
一个题没写完。明日补。
6.26
看DP的时候看见这个。
咦?这难道不是线段树吗- -
然而并没有update。于是可有更高效的算法。
于是发现了解决RMQ问题的ST算法。
之前有看见过ST。以为是什么高大上就没有看。
看了一下发现和线段树的二分一样。就像每个点下面有一个不能update的树。
预处理的时候至下而上的操作是DP。然后就可以O(1)query拉。
1 # include <iostream> 2 # include <cstdio> 3 # include <cmath> 4 # include <algorithm> 5 using namespace std; 6 # define maxn 100000+5 7 int num[maxn],MAX[maxn][20],MIN[maxn][20]; 8 9 int main(void) 10 { 11 int N,Q;cin>>N>>Q; 12 for(int i=1;i<=N;i++) 13 { 14 scanf("%d",num+i); 15 MAX[i][0]=MIN[i][0]=num[i]; 16 } 17 for(int j=1;j<20;j++) 18 for(int i=1;i<=N;i++) 19 if(i+(1<<j)-1<=N) 20 { 21 MAX[i][j]=max(MAX[i][j-1],MAX[i+(1<<j-1)][j-1]); 22 MIN[i][j]=min(MIN[i][j-1],MIN[i+(1<<j-1)][j-1]); 23 } 24 for(int i=0;i<Q;i++) 25 { 26 int m,n; scanf("%d%d",&m,&n); 27 int k=(log(double(n-m+1))/log(2)); 28 int ans=max(MAX[m][k],MAX[n-(1<<k)+1][k])-min(MIN[m][k],MIN[n-(1<<k)+1][k]); 29 printf("%d\n",ans); 30 } 31 return 0; 32 }
6.27
HDU 5266 pog loves szh III
上上周BC一个题。LCA+ST。学了ST之后立马翻出了这题。
中间还用到了dfs序。感觉处理的不是很棒。代码也丑。
时限开的6s。2s跑完还行吧。1次AC开心。
1 # pragma comment(linker, "/STACK:1024000000,1024000000") 2 # include <iostream> 3 # include <cstdio> 4 # include <cstring> 5 # include <vector> 6 # include <algorithm> 7 # include <cmath> 8 using namespace std; 9 # define maxn 300000+10 10 # define CLR(x) memset(x,0,sizeof(x)) 11 int t,pa[maxn],ans[maxn],MAX[maxn][20],MIN[maxn][20]; 12 bool vis[maxn]; 13 vector <int> vec[maxn]; 14 vector < pair<int,int> > query[maxn]; 15 16 int fa(int x) 17 { 18 return pa[x]==x?x:pa[x]=fa(pa[x]); 19 } 20 21 struct node 22 { 23 int no,time; 24 } T1[maxn],T2[maxn]; 25 26 void dfs(int i) 27 { 28 T1[i].no=i; T1[i].time=++t; 29 MAX[i][0]=MIN[i][0]=t; 30 for(int j=0;j<vec[i].size();j++) 31 if(!T1[vec[i][j]].time) dfs(vec[i][j]); 32 return; 33 } 34 35 bool cmp(node a,node b) 36 { 37 return a.time<b.time; 38 } 39 40 void LCA(int x) 41 { 42 for(int i=0;i<vec[x].size();i++) 43 if(T2[vec[x][i]].time>T2[x].time) 44 { 45 LCA(T2[vec[x][i]].no); 46 pa[T2[vec[x][i]].no]=x; 47 } 48 vis[x]=1; 49 for(int i=0;i<query[x].size();i++) 50 { 51 int a=query[x][i].first,b=query[x][i].second; 52 ans[a]=fa(b); 53 } 54 return; 55 } 56 57 int main(void) 58 { 59 int n; 60 while(cin>>n) 61 { 62 CLR(vis); CLR(T1); 63 for(int i=1;i<=n;i++) 64 { 65 pa[i]=i; 66 vec[i].clear(); 67 query[i].clear(); 68 } 69 for(int i=0;i<n-1;i++) 70 { 71 int b,c; scanf("%d%d",&b,&c); 72 vec[b].push_back(c); 73 vec[c].push_back(b); 74 } 75 t=0; dfs(1); 76 memcpy(T2,T1,sizeof(T2)); 77 sort(T1+1,T1+1+n,cmp); 78 for(int j=1;j<20;j++) 79 for(int i=1;i<=n;i++) 80 if(i+(1<<j)-1<=n) 81 { 82 MAX[i][j]=max(MAX[i][j-1],MAX[i+(1<<j-1)][j-1]); 83 MIN[i][j]=min(MIN[i][j-1],MIN[i+(1<<j-1)][j-1]); 84 } 85 int Q; scanf("%d",&Q); 86 for(int i=0;i<Q;i++) 87 { 88 int L,R; scanf("%d%d",&L,&R); 89 int k=(log(double(R-L+1))/log(2)); 90 int x=max(MAX[L][k],MAX[R-(1<<k)+1][k]); 91 int y=min(MIN[L][k],MIN[R-(1<<k)+1][k]); 92 query[T1[x].no].push_back(make_pair(i,T1[y].no)); 93 } 94 LCA(1); 95 for(int i=0;i<Q;i++) printf("%d\n",ans[i]); 96 } 97 return 0; 98 }