如何将时间限制传递给动态编程

时间:2014-05-31 15:58:03

标签: algorithm dynamic

我正在尝试如下问题: 如果出现以下情况,则说一个数字为369;

  • 3s的数量等于6s的数量,6s的数量等于9s的数量。
  • 3s的数量至少为1。

对于示例12369,383676989,396都是369个数字,而213,342143,111不是。

给定A和B找到区间[A,B]中有多少369个数字。打印答案模10 ^ 9 + 7

我接近制作dp sol的问题如下,但超出时间限制

long long  rec(vector<int>&v,int index,bool status,int cnt3,int cnt6,int cnt9)
{  
    sz=v.size()/3;
    if(cnt3>sz || cnt6>sz || cnt9>sz)
        return 0;
    if(index==v.size() && cnt3 && cnt3==cnt6 && cnt6==cnt9)
        return 1;
    else if(index==v.size())
        return 0;
    ll &ret=dp[index][status][cnt3][cnt6][cnt9];
    if(ret==-1)
    {
        ret=0;
        bool newstatus;
        for(int i=0;i<=9;i++)
        {
            if(status && i>v[index] )
                break;
            newstatus=status && (i==v[index]);
            if(i==3)
                ret+=rec(v,index+1,newstatus,cnt3+1,cnt6,cnt9);
            else if(i==6)
                ret+=rec(v,index+1,newstatus,cnt3,cnt6+1,cnt9);
            else if(i==9)
                ret+=rec(v,index+1,newstatus,cnt3,cnt6,cnt9+1);
            else
                ret+=rec(v,index+1,newstatus,cnt3,cnt6,cnt9);
            ret%=mod;
        }
    }
    return ret;
}

有人可以帮我优化吗?

1 个答案:

答案 0 :(得分:2)

提前终止

可能阻止许多州需要探索的一个简单变化是计算m = max(cnt3,cnt6,cnt9)。

为了获得匹配计数,你必须通过m-cnt3增加cnt3,通过m-cnt6增加cnt6,通过m-cnt9增加cnt9。

你有v.size() - 索引数字仍然要分配,所以你可以在你的功能开始时添加以下额外的测试

if (v.size()-index < m*3-cnt3-cnt6-cnt9)
  return 0;

压缩状态空间1

此外,如果我正确理解逻辑,一旦状态变为假,您就可以选择任何数字。从这一点开始,对于cnt3,cnt6,cnt9的任何排列结果都是相同的,所以你可以对这3个数字进行排序,以便进一步减少状态空间。

压缩状态空间2

同样,一旦所有计数都高于1,您就不必关心多少,以便您可以更改数字,例如:

cnt3=3,cnt6=7,cnt9=8

cnt3=1,cnt6=5,cnt9=6

这会导致您需要搜索更少的空间。