大白第一章第四节dp例题
#include<cstdio> using namespace std; const int N=1e4+5; int n,m,k,f[N]; int main(){ //f[i]表示第i次要删的数字 while(scanf("%d%d%d",&n,&k,&m)==3&&n){ //1 //f[1]=0; //for(int i=2;i<=n;i++) f[i]=(f[i-1]+k)%i; //int ans=(m-k+f[n]+1)%n; //2 //int s=0; //for(int i=2;i<=n;i++) s=(s+k)%i; //int ans=(m-k+s+1)%n;//这3句话来源于上面 //if(ans<=0) ans+=n; //printf("%d\n",ans); //3 int s=0; for(int i=2;i<n;i++) s=(s+k)%i; s=(s+m)%n; printf("%d\n",s+1); } return 0; }
//turn to lis #include<cstdio> #include<algorithm> using namespace std; const int N=1e5+5; int T,cas=1,n,p,q,pa[N],a[N],b[N],c[N]; inline void LIS(){ int len;c[len=1]=b[1]; for(int i=2,pos;i<=q+1;i++){ if(b[i]>c[len]) c[++len]=b[i]; else{ pos=lower_bound(c+1,c+len+1,b[i])-c; c[pos]=b[i]; } } printf("Case %d: %d\n",cas,len); } int main(){ for(scanf("%d",&T);cas<=T;cas++){ scanf("%d%d%d",&n,&p,&q); for(int i=1;i<=p+1;i++) scanf("%d",&a[i]),pa[a[i]]=i; for(int i=1;i<=q+1;i++) scanf("%d",&b[i]),b[i]=pa[b[i]]; LIS(); } return 0; } /*//lcs->TLE #include<cstdio> #include<cstring> #include<iostream> using namespace std; const int N=1e5+5; int T,cas=1,n,p,q,a[N],b[N],f[2][N*10]; int main(){ for(scanf("%d",&T);cas<=T;cas++){ scanf("%d%d%d",&n,&p,&q); for(int i=1;i<=p+1;i++) scanf("%d",&a[i]); for(int i=1;i<=q+1;i++) scanf("%d",&b[i]); memset(f,0,sizeof f);int now=0; for(int i=1;i<=p+1;i++){ now^=1; for(int j=1;j<=q+1;j++){ if(a[i]==b[j]) f[now][j]=f[now^1][j-1]+1; else f[now][j]=max(f[now][j-1],f[now^1][j]); } } printf("Case %d:%d\n",cas,f[now][q+1]); } return 0; } */
//朴素(AC) #include<cstdio> #include<cstring> //dp(i,j)表示选择[i,j]的子序列,在双方都采取最优策略,先手得分的最大值 //dp(i,j)=sum(i,j)-min{d(i+1,j)……d(j,j),d(i,j-1)……d(i,i)} #include<algorithm> using namespace std; const int N=105; int n,s[N],f[N][N]; bool vis[N][N]; int dp(int x,int y){ if(vis[x][y]) return f[x][y]; vis[x][y]=1; int m=0;//全部取光(精髓) for(int i=x+1;i<=y;i++) m=min(m,dp(i,y)); for(int i=x;i<y;i++) m=min(m,dp(x,i)); return f[x][y]=s[y]-s[x-1]-m; } int main(){ while(scanf("%d",&n)==1&&n){ for(int i=1;i<=n;i++) scanf("%d",&s[i]),s[i]+=s[i-1]; memset(vis,0,sizeof vis); printf("%d\n",2*dp(1,n)-s[n]); } return 0; }
//辅助数组优化 //f(i,j)=min{d(i,j),d(i+1,j)……d(j,j)} //g(i,j)=min{d(i,j),d(i,j-1)……d(i,i)} #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=105; int n,a[N],s[N],f[N][N],g[N][N],dp[N][N]; int main(){ while(scanf("%d",&n)==1&&n){ memset(f,0,sizeof f); memset(g,0,sizeof g); for(int i=1;i<=n;i++) scanf("%d",&a[i]),f[i][i]=g[i][i]=dp[i][i]=a[i]; for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i]; for(int L=1;L<n;L++){ for(int i=1;i+L<=n;i++){ int j=i+L; int m=0; m=min(m,f[i+1][j]); m=min(m,g[i][j-1]); dp[i][j]=s[j]-s[i-1]-m; f[i][j]=min(dp[i][j],f[i+1][j]); g[i][j]=min(dp[i][j],g[i][j-1]); } } printf("%d\n",2*dp[1][n]-s[n]); } return 0; }
#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int N=1<<17; int n,cas; int p[N],cover[N],f[N]; int main(){ while(scanf("%d",&n)==1&&n){ memset(p,0,sizeof p); memset(cover,0,sizeof cover); for(int i=0,m,x;i<n;i++){ scanf("%d",&m); p[i]=1<<i; while(m--) scanf("%d",&x),p[i]|=(1<<x); } for(int S=0;S<(1<<n);S++){ cover[S]=0; for(int i=0;i<n;i++) if(S&(1<<i)) cover[S]|=p[i]; } //dp transfer equation: //f(S)=max{f(S-S0)|S0 belong to S,and cover[S0]==ALL} int ALL=(1<<n)-1;f[0]=0; for(int S=1;S<(1<<n);S++){ f[S]=0; for(int S0=S;S0;S0=(S0-1)&S){ if(cover[S0]==ALL) f[S]=max(f[S],f[S^S0]+1); } } printf("Case %d: %d\n",++cas,f[ALL]); } return 0; }
#include<cstdio> #include<cstring> #include<vector> using namespace std; const int N=1005; const int M=2000; int n,m,T,f[N][N];bool vis[N][N]; vector<int>graph[N]; int dp(int i,int j,int fa){ if(vis[i][j]) return f[i][j]; vis[i][j]=1; int &ans=f[i][j]; ans=M; //1:now point with light for(int k=0;k<graph[i].size();k++){ if(graph[i][k]!=fa){ ans+=dp(graph[i][k],1,i); } } if(!j&&fa>=0) ans++;//not root if(j||fa<0){ //2:now point without light int sum=0; for(int k=0;k<graph[i].size();k++){ if(graph[i][k]!=fa){ sum+=dp(graph[i][k],0,i); } } if(fa>=0) sum++;//not root ans=min(ans,sum); } return ans; } int main(){ for(scanf("%d",&T);T--;){ scanf("%d%d",&n,&m); for(int i=0;i<n;i++) graph[i].clear(); for(int i=0,x,y;i<m;i++){ scanf("%d%d",&x,&y); graph[x].push_back(y); graph[y].push_back(x); } memset(vis,0,sizeof vis); int ans=0; for(int i=0;i<n;i++){ if(!vis[i][0]){ ans+=dp(i,0,-1); } } //ans=Ma+b;beacause DAG printf("%d %d %d\n",ans/M,m-ans%M,ans%M); } return 0; }
#include<cstdio> using namespace std; const int N=1e5+5; int T,c,n,x[N],y[N]; int dist2origin[N],total_dist[N],total_wight[N]; int q[N],f[N]; inline int ABS(int x){ return x>0?x:-x; } //dp[i]=min{dp[j]+dist2origin[j+1]+dist[j+1,i]+dist2origin[i]|j<=i,w[j+1,i]<=c} //==>min{dp[j]+dist2origin[j+1]-total_dist[j+1]}+total_dist[i]+dist2origin[i] // (let total_dist[i]=w1+w2+……+wi,then dist[j+1,i]=total_dist[i]-total_dist[j+1]) //==>min{func(j)}+total_dist[i]+dist2origin[i]; // (let func(j)=dp[j]+dist2origin[j+1]-total_dist[j+1]) //use humdrum queue to optimize time.(finised) inline int func(int j){ return f[j]+dist2origin[j+1]-total_dist[j+1]; } int main(){ for(scanf("%d",&T);T--;){ scanf("%d%d",&c,&n); dist2origin[0]=total_dist[0]=total_wight[0]=x[0]=y[0]=0; for(int i=1,w;i<=n;i++){ scanf("%d%d%d",&x[i],&y[i],&w); dist2origin[i]=ABS(x[i])+ABS(y[i]); total_dist[i]=total_dist[i-1]+ABS(x[i]-x[i-1])+ABS(y[i]-y[i-1]); total_wight[i]=total_wight[i-1]+w; } int h=0,t=0; for(int i=1;i<=n;i++){ for(;h<t&&total_wight[i]-total_wight[q[h]]>c;h++); f[i]=func(q[h])+total_dist[i]+dist2origin[i]; for(;h<t&&func(i)<=func(q[t]);t--); q[++t]=i; } printf("%d\n",f[n]); if(T>0) putchar('\n'); } return 0; }
//dp transfer equation: //dp(r,c,S) //1 dp(r0,c,S0)=dp(r-r0,c,S-S0){1<=r0<r} //2 dp(r,c0,S0)=dp(r,c-c0,S-S0){1<=c0<c} //3 dp(r,c,S)=dp(c,r,S) //use g(r,S) take place of dp(r,c,S){r<=c}, and judge whether is legal or not. #include<cstdio> #include<cstring> #include<iostream> using namespace std; const int N=16,M=105; int T,n,cas,x,y,a[N],sum[1<<N]; bool f[1<<N][M],vis[1<<N][M]; int bitcount(int x){ return !x?0:bitcount(x>>1)+(x&1); } bool dp(int S,int x){ if(vis[S][x]) return f[S][x]; vis[S][x]=1; bool &ans=f[S][x]; if(bitcount(S)==1) return ans=1; int y=sum[S]/x; for(int S0=(S-1)&S;S0;S0=(S0-1)&S){ int S1=S-S0; if(!(sum[S0]%x)&&dp(S0,min(x,sum[S0]/x))&&dp(S1,min(x,sum[S1]/x))) return ans=1; if(!(sum[S0]%y)&&dp(S0,min(y,sum[S0]/y))&&dp(S1,min(y,sum[S1]/y))) return ans=1; } return ans=0; } int main(){ while(scanf("%d",&n)==1&&n){ scanf("%d%d",&x,&y); memset(vis,0,sizeof vis); memset(f,0,sizeof f); for(int i=0;i<n;i++) scanf("%d",&a[i]); for(int S=1;S<(1<<n);S++){ sum[S]=0; for(int i=0;i<n;i++){ if(S&(1<<i)) sum[S]+=a[i]; } } int ALL=(1<<n)-1;bool ans; if(sum[ALL]!=x*y||sum[ALL]%x) ans=0; else ans=dp(ALL,min(x,y)); printf("Case %d: %s\n",++cas,ans?"Yes":"No"); } return 0; }