1. 程式人生 > 其它 >數字遊戲(NOIP 2003 PJT2)

數字遊戲(NOIP 2003 PJT2)

一 原始資料處理
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},{-13}和{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 }