zoukankan      html  css  js  c++  java
  • [DP]JZOJ 3046 游戏

    Description

    游戏规则如下:给定两个正整数数列,一个游戏者通过若干次操作完成游戏。每一次操作,选择两个正整数k1和k2。将第一个数列的最后连续k1个数删除,它们的和记为S1;将第二个数列的最后连续K2个数删除,它们的和记为S2。这一次操作的得分就是(S1-K1)* (S2-K2 )。直到两个数列都清空了为止,所以不允许一个数列空了,而另一个数列中还有数。游戏的总得分就是每一次操作的得分总和。求最小的总得分。 

     

    Input

    第一行是两个整数L1和L2,分别表示第一个数列和第二个数列的初始长度。 


    第二行有L1个正整数,是第一个数列的数。 


    第三行有L2个正整数,是第二个数列的数。 


    数列中的数都不超过1000。 

    Output

    一个整数,表示最小的总得分。 

     

    Sample Input

    3 2
    1 2 3
    1 2

    Sample Output

    2
     

    Data Constraint

     
     

    Hint

    对于20%的数据,L1,L2<=20; 


    对于40%的数据,L1,L2<=200;


    对于100%的数据,1<=L1,L2<=2000。

    分析

    对于$(k1-s1)*(k2-s2)$这个柿子,不难发现$k1-s1=Sigma k-1$

    所以事先给所有值-1,柿子变成$k1*k2=Sigma k1_i imesSigma k2_i$

    DP的柿子就是$f[i][j]=min(f[i+1][j],f[i+1][j+1],f[i][j+1])+a[i]*b[j]$

    #include <iostream>
    #include <cstdio>
    #include <memory.h>
    using namespace std;
    const int N=2e3+10;
    int l1,l2;
    int a[N],b[N],f[N][N];
    
    int main() {
        scanf("%d%d",&l1,&l2);
        for (int i=1;i<=l1;i++) scanf("%d",&a[i]),a[i]--;
        for (int i=1;i<=l2;i++) scanf("%d",&b[i]),b[i]--;
        memset(f,0x7f,sizeof f);
        f[l1+1][l2+1]=0;
        for (int i=l1;i;i--)
            for (int j=l2;j;j--)
                f[i][j]=min(f[i+1][j],min(f[i+1][j+1],f[i][j+1]))+a[i]*b[j];
        printf("%d",f[1][1]);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    .NET Core log4net 使用(转贴)
    Tomcat的工作原理
    Servlet工作原理
    java实现快速排序
    正则表达式积累
    js常用知识真理
    最常用的的设计模式
    【设计模式】单例设计模式
    java中堆栈区别,递归和迭代区别
    Struts2的工作原理
  • 原文地址:https://www.cnblogs.com/mastervan/p/11136096.html
Copyright © 2011-2022 走看看