【洛谷P1282】多米诺骨牌

啊啊啊啊,这道题搞了一晚上,简直要疯了,其实就是一道很简单的背包DP,一眼就看出来了,但是各种修改每次都是55分,最后发现好像除了第一次以后都不能从j=0开始转移,就是说每次都必须选一项,其实也不是很懂发题解的人为什么空间优化之后只要把j=0给覆盖掉就好了,而不考虑以后的错误转移,应该是可以用数学证明的= =但是蒟蒻就是不会啊,所以以后这样的题还是仔细的考虑一下能不能空间优化吧,如果自己不去管那绝对足够了的空间复杂度,绝对不会浪费一晚上的QAQ。

#include//p1282多米诺骨牌 
#include
#include
#include
#include
#define min(a,b) (a
#define max(a,b) (a>b?a:b)
using namespace std;

int sum,up,a[1010],b[1010],dp[30000],maxc,tot,bound,ans,n;

int main()//dp,状态f[i][j]表示前i个达到j的最少步数,01背包 
{
    cin>>n;//可优化空间,还可常数优化 
    sum=0;//因为要判断是否可以到达,先赋初值为最大值 
    maxc=0;
    memset(dp,0x3f,sizeof(dp));
    dp[0]=0;
    for (int i=1;i<=n;i++)
    {
        cin>>a[i]>>b[i];
        sum+=a[i]+b[i];
    }
    tot=sum;
    for (int i=1;i<=n;i++)
    {
        maxc+=max(a[i],b[i]);
        bound=min(a[i],b[i]);
         for (int j=maxc; j>=0; j--)
        {
            int tmp=50000; //tmp代表取此物品更优秀的方式,并且强制地取 
            if (j>=a[i]) tmp=dp[j-a[i]];
            if (j>=b[i]) tmp=min(tmp,dp[j-b[i]]+1);
            dp[j]=tmp;
        }
    }
    sum>>=1;
    while(1)
    {
        ans=min(dp[sum],dp[tot-sum]);
        if (ans<30000) break;
        sum--;
    }
    cout<return 0;
}

你可能感兴趣的:(动态规划)