zoukankan      html  css  js  c++  java
  • 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。

     

    分析

      

    • 首先我们直接全部减一,答案就是s1*s2了
    • WHY??
    • 我们取k1数,又减去k1个数,不就等于每个数减一吗
    • 然后我们就分析怎么样去才是最小的呢
    • 因为答案是乘积,两个越大,答案就越大
    • 所以一次取一个是最好的
    • 但是数列的位数是不一定的
    • 所以我们要分情况讨论
    • f[i][j]为第一列删掉了i个,第二列删掉了j个
    • 因为每次取一个是最好的
    • 所以f[i][j]=f[i-1][j-1]+a[i]*a[j]
    • 然后就是第一列多取 f[i][j]=f[i-1][j]+a[i]*b[j]
    • 因为a*(b+c)=a*b+a*c
    • 所以因为我们f[i-1][j]中已经有a*b了
    • 所以我们还是只需要加上a[i]*b[j]

     

    代码

     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 int a[100001],b[100001];
     5 int f[2010][2011];
     6 int main ()
     7 {
     8     int n,m;
     9     cin>>n>>m;
    10     memset(f,0x3f,sizeof(f));
    11     f[0][0]=0; 
    12     for (int i=1;i<=n;i++)
    13        cin>>a[i],a[i]--;
    14     for (int i=1;i<=m;i++)
    15        cin>>b[i],b[i]--;
    16     for (int i=1;i<=n;i++)
    17       for (int j=1;j<=m;j++)
    18         f[i][j]=min(f[i-1][j-1],min(f[i-1][j],f[i][j-1]))+a[i]*b[j];
    19     cout<<f[n][m];
    20  } 

     

    为何要逼自己长大,去闯不该闯的荒唐
  • 相关阅读:
    前端之JavaScript
    前端之CSS
    前端之HTML
    编程总结
    线程
    锁机制,信号机制,事件机制
    并发编程
    struct
    linux查看端口
    vue页面跳转传参
  • 原文地址:https://www.cnblogs.com/zjzjzj/p/11134967.html
Copyright © 2011-2022 走看看