zoukankan      html  css  js  c++  java
  • 区间动归

    石子合并

    链接

    分析:dp[i][j]表示从i顺时针数j个位置的最大值,规划方向是顺推,初始时dp[i][i]=0。显然,我们需要求出合并个数为2,3,,,,n的情况,对于dp[i][j]我们假设最后一次合并位置为k,dp[i][j]=dp[i][k]+dp[k+1][j]+sum[i,j],因为sum[i,j]表示i到j这段和,跟k取的位置无关,由此可以得到dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]),最大值同理

     1 #include "iostream"
     2 #include "cstdio"
     3 #include "cstring"
     4 #include "string"
     5 using namespace std;
     6 const int maxn=200+10;
     7 const int INF=1<<30;
     8 int f[maxn][maxn]; //max
     9 int dp[maxn][maxn]; //min
    10 int sum[maxn],a[maxn];
    11 int n;
    12 int main()
    13 {
    14     cin>>n;
    15     for(int i=1;i<=n;i++){
    16         cin>>a[i];
    17         sum[i]=sum[i-1]+a[i];
    18     }
    19     for(int i=n+1;i<=2*n;i++)
    20         sum[i]=sum[n]+sum[i-n];
    21     for(int i=1;i<=2*n;i++)
    22         for(int j=1;j<=2*n;j++)
    23             dp[i][j]=INF;
    24     for(int i=1;i<=2*n;i++)  dp[i][i]=0;
    25     for(int l=1;l<=n;l++){
    26         for(int i=1;i<=2*n-l;i++){
    27             int j=i+l;
    28             for(int k=i;k<j;k++){
    29                 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
    30             }
    31         }
    32     }
    33     memset(f,0,sizeof(f));
    34     for(int l=1;l<=n;l++){
    35         for(int i=1;i<=2*n-l;i++){
    36             int j=i+l;
    37             for(int k=i;k<j;k++){
    38                 f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+sum[j]-sum[i-1]);
    39             }
    40         }
    41     }
    42     int cnt=0,ans=INF;
    43     for(int i=1;i<=n;i++)
    44         cnt=max(f[i][i+n-1],cnt);
    45     for(int i=1;i<=n;i++)
    46         ans=min(dp[i][i+n-1],ans);
    47     cout<<ans<<endl<<cnt<<endl;
    48 }
    View Code

    能量项链

    链接

    分析:dp[i][j]表示i到j这段区间的最大值,我们需要枚举从哪个点切分,但是注意一个问题,对于一次获得能量,我们所需要用到的是a[i]和a[i+1]的值,所以可以得到状态转移方程dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+(a[i]*a[k+1]*a[j+1]))

     1 #include "iostream"
     2 #include "cstdio"
     3 #include "cstring"
     4 #include "string"
     5 using namespace std;
     6 const int maxn=200+10;
     7 int a[maxn];
     8 int dp[maxn][maxn];
     9 int n;
    10 int main()
    11 {
    12     cin>>n;
    13     for(int i=1;i<=n;i++){
    14         cin>>a[i];
    15         a[i+n]=a[i];
    16     }
    17     for(int l=1;l<=n;l++){
    18         for(int i=1;i<=2*n-l;i++){
    19             int j=i+l;
    20             for(int k=i;k<j;k++){
    21                 dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+(a[i]*a[k+1]*a[j+1]));
    22             }
    23         }
    24     }
    25     int cnt=0;
    26     for(int i=1;i<=n;i++)
    27         cnt=max(cnt,dp[i][i+n-1]);
    28     cout<<cnt<<endl;
    29 }
    View Code

    数字游戏

    链接

    分析:dp[i][j][z]表示区间[i,j]被分成z段的最大值,故dp[i][j][z]=max(dp[i][j][z],dp[i][k][z-1]*dp[k+1][j][1]),最小值同理

     1 #include "iostream"
     2 #include "cstdio"
     3 #include "cstring"
     4 #include "string"
     5 using namespace std;
     6 const int maxn=100+10;
     7 const int INF=1<<30;
     8 int n,m;
     9 int a[maxn],sum[maxn];
    10 int dp[maxn][maxn][20];  //max
    11 int f[maxn][maxn][20];  //min
    12 int main()
    13 {
    14     cin>>n>>m;
    15     for(int i=1;i<=n;i++){
    16         cin>>a[i];
    17         sum[i]=sum[i-1]+a[i];
    18     }
    19     for(int i=n+1;i<=2*n;i++)
    20         sum[i]=sum[n]+sum[i-n];
    21     memset(dp,0,sizeof(dp));
    22     for(int i=1;i<=2*n;i++)
    23         for(int j=1;j<=2*n;j++)
    24             for(int z=1;z<=m;z++)
    25                 f[i][j][z]=INF;
    26     for(int i=1;i<=2*n;i++){
    27         for(int j=1;j<=2*n;j++){
    28             dp[i][j][1]=sum[j]-sum[i-1];
    29             f[i][j][1]=sum[j]-sum[i-1];
    30             while(dp[i][j][1]<0) dp[i][j][1]+=10;
    31             dp[i][j][1]%=10;
    32             while(f[i][j][1]<0)  f[i][j][1]+=10;
    33             f[i][j][1]%=10;
    34         }
    35     }
    36     for(int l=1;l<=n;l++){
    37         for(int i=1;i<=2*n-l;i++){
    38             int j=i+l;
    39             for(int k=i;k<j;k++){
    40                 for(int z=2;z<=m;z++)
    41                     dp[i][j][z]=max(dp[i][j][z],dp[i][k][z-1]*dp[k+1][j][1]);
    42             }
    43         }
    44     }
    45     for(int i=1;i<=2*n;i++)
    46         for(int z=2;z<=m;z++)
    47             f[i][i][z]=0;
    48     for(int l=1;l<=n;l++){
    49         for(int i=1;i<=2*n-l;i++){
    50             int j=i+l;
    51             for(int k=i;k<j;k++){
    52                 for(int z=2;z<=m;z++)
    53                     f[i][j][z]=min(f[i][j][z],f[i][k][z-1]*f[k+1][j][1]);
    54             }
    55         }
    56     }
    57     int cnt=0,ans=INF;
    58     for(int i=1;i<=n;i++)
    59         cnt=max(dp[i][i+n-1][m],cnt);
    60     for(int i=1;i<=n;i++)
    61         ans=min(f[i][i+n-1][m],ans);
    62     cout<<ans<<endl<<cnt<<endl;
    63 }
    View Code
  • 相关阅读:
    android 多渠道打包
    第三方授权认证(一)实现第三方授权登录、分享以及获取用户资料
    Android:支持不同分辨率的屏幕设计 .
    动画效果编程基础--AnimationAndroid
    Android使用尺寸资源 dimens .
    android手机分辨率整理
    线程和进程
    js和html的结合方式
    成员变量和局部变量
    MySQL基础知识
  • 原文地址:https://www.cnblogs.com/wolf940509/p/7191724.html
Copyright © 2011-2022 走看看