-
F - Removal Game
- Gym - 101196F
- 区间DP模板题 : 三重for枚举长度、起点、中间值,注意预处理gcd否则超时
- 它独特之出就是最终剩下的两个没有中间点价值可以按照他们两个的gcd来计算,由于是环的特性可以有两种思路
- 一、在原来区间DP模板基础上起点不需要有i+len<n的限制了直接i<n即可这样j与k的大小需要%n
- 二、直接先拷贝一遍长短扩到2*n然后首尾在分别拷贝一个按照长度为2*n+1的序列来跑区间DP
- 两种方法最后处理最优解也有所不同一、dp[i][j]+dp[j][i]+g[i][j]。二、dp[i][j]+dp[j][i+n]+g[i][j]。
-
#include<bits/stdc++.h> using namespace std; #define maxn 333 #define inf 0x3f3f3f3f int n,a[maxn],ans; int dp[maxn][maxn]; int g[maxn][maxn]; int main() { while(~scanf("%d",&n)) { if(!n)break; for(int i=0; i<n; i++) scanf("%d",&a[i]); ans=inf; for(int i=0; i<n; i++) for(int j=i+1; j<n; j++) g[j][i]=g[i][j]=__gcd(a[i],a[j]); for(int len=1; len<n; len++) for(int i=0; i<n; i++) { int j=i+len; if(j>=n)j-=n; if(len==1)dp[i][j]=0; else dp[i][j]=inf; for(int k=(i+1)%n; k!=j; k=(k+1)%n) dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+g[i][j]); } for(int i=0; i<n; i++) for(int j=i+1; j<n; j++) ans=min(ans,dp[i][j]+dp[j][i]+g[i][j]); printf("%d\n",ans); } return 0; }
#include<bits/stdc++.h> using namespace std; #define maxn 333 #define inf 0x3f3f3f3f int n,a[maxn],ans; int dp[maxn][maxn]; int g[maxn][maxn]; int main() { while(~scanf("%d",&n)) { if(!n)break; for(int i=1; i<=n; i++) { scanf("%d",&a[i]); a[i+n]=a[i]; } a[0]=a[n]; a[2*n+1]=a[1]; ans=inf; for(int i=0; i<=2*n+1; i++) for(int j=i+1; j<=2*n+1; j++) g[j][i]=g[i][j]=__gcd(a[i],a[j]); for(int len=2; len<=2*n+1; len++) for(int i=0; i+len<=2*n+1; i++) { int j=i+len; dp[i][j]=inf; for(int k=i+1; k<j; k++) dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+g[i][j]); } for(int i=1; i<=n; i++) for(int j=i+1; j<i+n; j++) ans=min(ans,dp[i][j]+dp[j][i+n]+g[i][j]); printf("%d\n",ans); } return 0; }
F - Removal Game Gym -环状区间DP
最新推荐文章于 2021-02-28 22:42:10 发布