一道好题

LELElele01

2019-07-16 20:59:05

Personal

[环](http://www.gdfzoj.com/oj/contest/570/problems/4) ## 因为有环,所以先开2倍空间,套同区间dp $$ $$ 已经开了2倍空间,可以线性枚举 $,$显然可以用区间dp ## $dp[l][r]$ ## 删除 ($ l $,$ r $) 后最后取$l,r$的最小价值 $$ $$ $dp[i][i+1]$ 为0 $$ $$ ```c for(int len=3;len<=n;len++) for(l=1; l+len-1<=n;l++) r=l+len-1 ``` $$ $$ $$ $$ ``` for(intk=l+1;k<r;k++) dp[i][j]=min(dp[i][k]+dp[k][r]+gcd(val[l],val[r])) ``` $$ $$ 即取走k的价值 $$ $$ 套用区间dp模板即可 $$ $$ $$ $$ $$ $$ $$ $$ $dp[l][r]$ 使$r-l+1$=n AC代码:(时间复杂度较高,但数据水,能过) ```c #include<bits/stdc++.h> using namespace std; const int N=110,MAX=1111001; int n; int val[N*2]; int dp[N*2][N*2]; int gcd(int x,int y) { return x%y==0?y:gcd(y,x%y); } int main(){ scanf("%d",&n); while(n){ for(int i=1;i<=n;i++){ scanf("%d",&val[i]); } for(int i=1;i<n;i++) val[n+i]=val[i]; for(int i=1;i<=n;i++)dp[i][i+1]=0; for(int len=3;len<=n;len++){ for(int l=1;l+len-1<2*n;l++){ int r=l+len-1; dp[l][r]=MAX; for(int k=l+1;k<r;k++){ dp[l][r]=min(dp[l][r],dp[l][k]+dp[k][r]+gcd(val[l],val[r])); } } } int ans=MAX; for(int l=1;l<n;l++){ for(int j=l+1;j<=n;j++){ ans=min(ans,dp[l][j]+dp[j][l+n]+gcd(val[l],val[j])); } } printf("%d\n",ans); scanf("%d",&n); } } ``` 正解 ```c #include<bits/stdc++.h> using namespace std; const int N=110,MAX=1111001; int n; int val[N*2]; int dp[N*2][N*2],g[N*2][N*2]; int gcd(int x,int y) { return x%y==0?y:gcd(y,x%y); } int main(){ scanf("%d",&n); while(n){ for(int i=1;i<=n;i++){ scanf("%d",&val[i]); } for(int i=1;i<=n;i++) val[n+i]=val[i]; for(int l=1;l<2*n;l++) for(int r=l+1;r<=2*n;r++){ //printf("r:%d",l);puts("check"); g[l][r]=gcd(val[l],val[r]); //g[r][l]=g[l][r]; } for(int i=1;i<=n;i++)dp[i][i+1]=0; for(int len=3;len<=n;len++){ for(int l=1;l+len-1<2*n;l++){ int r=l+len-1; dp[l][r]=MAX; int gd=g[l][r]; for(int k=l+1;k<r;k++){ dp[l][r]=min(dp[l][r],dp[l][k]+dp[k][r]+gd); } } } int ans=MAX; for(int l=1;l<n;l++){ for(int j=l+1;j<=n;j++){ int gd=g[l][j]; ans=min(ans,dp[l][j]+dp[j][l+n]+gd);//非常重要 } } printf("%d\n",ans); scanf("%d",&n); } } ``` ## 只剩3个数的时候一定要再比一次!!! 因为前面对$len$的处理,默认$dp[l][l+n]$ 会最后取$l,l+n,$ $$ $$ 假设最后3个数为$l,j,l+n$ $$ 可能先取l+n或l更优