首页 > 其他 > 详细

洛谷4141消失之物——每个体积的角度

时间:2018-06-16 10:18:10      阅读:183      评论:0      收藏:0      [点我收藏+]

题目: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("\n");
    }
    return 0;
}

 

洛谷4141消失之物——每个体积的角度

原文:https://www.cnblogs.com/Narh/p/9189491.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!