zoukankan      html  css  js  c++  java
  • 洛谷4141消失之物——每个体积的角度

    题目:https://www.luogu.org/problemnew/show/P4141

    这道题教会我dp的新姿势。

    从每一个体积来看比较方便。

      发现对于一个特定的体积,它从1~n的变化轨迹就是不断地+=dp[ k-a[i] ]。(dp[ k-a[i] ]保证没有选 i (倒序!))

    所以不选 i 对于这个体积来说竟然就是 - = dp[ k-a[i] ]!

    于是可以先n^2求出到最后所有的体积对应的方案,然后去各个地方 - = dp[ k-a[i] ]。

    需要注意的是直接减的话,dp[ k-a[i] ]里是包含了“选 i ”这种情况的。

      正好自己正在求“不选 i ”的种种体积,所以就再开一个数组,正序遍历,用刚才求出的值就好了。

    我还在想什么正着dp再倒着dp之类,结果还是n^3;

      看看别人,发现简单地n^3竟然就是枚举 i 不选,然后正常n^2,从1~n遍历到 i 的时候直接跳过……

      这道题之所以可以随便加加减减、跳过什么的,可能因为仔细分析一下,它只涉及加减,与乘什么的没有关系,所以交换律使得可以任意时刻直接减掉不需要的。

    但是从每一个体积来分析,得出思路是很重要的角度。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=2005;
    int n,m,a[N],dp[N],tp[N];
    int rdn()
    {
        int ret=0;char ch=getchar();
        while(ch>'9'||ch<'0')ch=getchar();
        while(ch>='0'&&ch<='9')(ret*=10)+=ch-'0',ch=getchar();
        return ret;
    }
    int main()
    {
        n=rdn();m=rdn();
        for(int i=1;i<=n;i++)a[i]=rdn();
        dp[0]=1;
        for(int i=1;i<=n;i++)
            for(int j=m;j>=a[i];j--)//倒序 
                (dp[j]+=dp[j-a[i]])%=10;
        for(int i=1;i<=n;i++)
        {
            memcpy(tp,dp,sizeof dp);
            for(int j=1;j<=m;j++)
            {
                tp[j]=(dp[j]-(j>=a[i]?tp[j-a[i]]:0)+10)%10;//不然dp[j-a[i]]里包含选了一个a[i]的情况 
                printf("%d",tp[j]%10);
            }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    java中compareTo()用法详解
    random详解
    http协议介绍
    各种Web渗透测试平台
    提升黑客技能的十大网站
    .htaccess文件得用途
    XSS平台搭建
    session攻击(会话劫持+固定)与防御
    伪静态的原理以及应用
    Nessus激活码获取
  • 原文地址:https://www.cnblogs.com/Narh/p/9189491.html
Copyright © 2011-2022 走看看