數字遊戲(NOIP 2003 PJT2)
阿新 • • 發佈:2022-05-29
一 原始資料處理 1.輸入資料得到a[1]~a[n],複製擴充套件a[n+1]~a[2*n],以便處理不同點為起點出發。 cin>>n>>m; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); a[i+n]=a[i]; } 2.計算字首和 sum[1]=a[1]; for(int i=2;i<=2*n;i++) sum[i]=sum[i-1]+a[i]; 3.除餘計算函式 int mod10(int k) { return (k%10+10)%10; } 二 dp陣列定義及轉移方程 1 dp定義 dpma [i][j][m] 表示i為起點j為終點,劃分m份的最大值; dpmi [i][j][m] 表示i為起點j為終點,劃分m份的最小值;2 根據定義初始化 dpma [i][j][1]; dpmi [i][j][1]; for(int i=1;i<=2*n;i++) { for (int j=i;j<=2*n;j++) { dpmi[i][j][1]=dpma[i][j][1]=mod10(sum[j]-sum[i-1]); for(int len=2;len<=m;len++) { dpmi[i][j][len]=2e9; dpma[i][j][len]=0; } } } 3轉移方程: dpma[i][j][len]=max(1ll*dpma[i][mid][num]*dpma[mid+1][j][len-num],1ll*dpma[i][j][len])); dpmi[i][j][len]=min(1ll*dpmi[i][mid][num]*dpmi[mid+1][j][len-num],1ll*dpmi[i][j][len])); len 範圍[2,m],最外層迴圈,用來遍歷所有分的份數(因為份數為1的都已初始化) num是分堆數量取值範圍[1,len-1],用來遍歷len堆的方法,len=5,那麼num可分成1,4;2,3;3,2;4,1; i的範圍[1,2*n],j的範圍[i,2*n],用來遍歷起始點。 mid為i~j之間的劃分點 ,mid 取值範圍[i,j-1] 舉例說明mid的必要性,樣例a[]={2,-1,3,4}, 求dp[1][3][2], 存在{2},{-1,3}和{2,-1},{3}按照劃mid分點不同存在兩種情況, 應比較dp[1][1][1]*dp[2][3][1]和dp[1][2][1]*dp[3][3][1]兩者取大 防止dpmi超int界,乘1ll轉化為長整型 4 求最大最小值 int maxans=0,minans=2e9; for(int i=1;i<=n;i++) { maxans=max(dpma[i][i+n-1][m],maxans); minans=min(dpmi[i][i+n-1][m],minans); }
程式碼:
1 #include<bits/stdc++.h> 2 #define LL long long 3 using namespace std; 4 int dpmi[200][200][200],dpma[200][200][200]={0}; 5 int n,m,a[200]={0},sum[200]={0}; 6 int mod10(int n) 7 { 8 return (n%10+10)%10; 9 } 10 11 int main() 12 { 13 // freopen("1.in","r",stdin); 14 // freopen("1.out","w",stdout); 15 cin>>n>>m; 16 for(int i=1;i<=n;i++) 17 { 18 scanf("%d",&a[i]); 19 a[i+n]=a[i]; 20 } 21 22 sum[1]=a[1]; 23 for(int i=2;i<=2*n;i++) sum[i]=sum[i-1]+a[i]; 24 25 for(int i=1;i<=2*n;i++) 26 { 27 for(int j=i;j<=2*n;j++) 28 { 29 dpmi[i][j][1]=dpma[i][j][1]=mod10(sum[j]-sum[i-1]); 30 for(int len=2;len<=m;len++) 31 { 32 dpmi[i][j][len]=2e9; 33 dpma[i][j][len]=-1; 34 } 35 } 36 } 37 38 39 for(int len=2;len<=m;len++) 40 { 41 for(int num=1;num<len;num++) 42 { 43 for(int i=1;i<=2*n;i++) 44 { 45 for(int j=i;j<=2*n;j++) 46 { 47 for(int mid=i;mid<=j-1;mid++) 48 { 49 dpma[i][j][len]=max(1ll*dpma[i][mid][num]*dpma[mid+1][j][len-num],1ll*dpma[i][j][len]); 50 dpmi[i][j][len]=min(1ll*dpmi[i][mid][num]*dpmi[mid+1][j][len-num],1ll*dpmi[i][j][len]); 51 } 52 } 53 } 54 } 55 } 56 int maxans=-1000,minans=2e9; 57 for(int i=1;i<=n;i++) 58 { 59 maxans=max(dpma[i][i+n-1][m],maxans); 60 minans=min(dpmi[i][i+n-1][m],minans); 61 } 62 printf("%d\n%d",minans,maxans); 63 return 0; 64 }