p1836

其实也不算难,搜索一下后模拟就好。第一眼看到的时候看错成密码长度<=10^16,马上就关了。然后一想不可能啊连输入都超时还怎么做,又拐回来看了一眼,就发现还好。

题目要求对密码长度分解成一群平方和的和,数量最少,数量一样时最大的矩阵最大,最大的矩阵一样时第二大的矩阵最大,以此类推。

这个分解操作有点东西的,又不能循环,只好上一个搜索。然后还不知道矩阵数量,于是就想到了迭代加深搜索。

迭代加深搜索是不知道深度或者在最大深度以前也可能有解且直接搜最大深度的复杂度过大的时候应用的一种方法(也就是搜索树的规模随层次的深入增长过快且确保答案能在一个较浅的节点时)。

我们每次搜索的时候规定好搜索深度,如果当前搜索深度找不到就算了,深度加一继续重新开始找。

我在搜索的时候带着刚加入的值进入下一层,他就是答案数列中的当前最小值。在下一层中新增的矩阵长度不会大于当前最小值,向1逐渐减小。这样就确保了只要搜到就一定是满足条件的最优的矩阵。

 

一旦找到划分方案就地输出

一个sum记录前一个矩阵的最后一个元素,它的初始值为0,当前矩阵输出后就再加上ans[i]*ans[i]。

k和f我也不知道怎么讲,你们可以自己手推一下。

再详细的代码实现就再下面了。

using namespace std;
int i,f,k;
int n,ans[70000];
string s;
void dfs(int sum,int now,int max)
{
    if(now==k+1)
    {
        if(sum==0)
        {
            for(i=1;i<=k;i++)
                for(f=0;f<ans[i];f++)
                    for(k=0;k<ans[i];k++)    
                        cout<<s[sum+k*ans[i]+f];
                sum+=ans[i]*ans[i];
            exit(0);
        }
        return ;
    }
    for(int f=max;f>=1;f--)
    {
        if(f*f<=sum)
        {
            ans[now]=f;
            dfs(sum-f*f,now+1,f);
        }        
    }
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
//freopen("123.in","r",stdin);
//freopen("123.out","w",stdout);
    getline(cin,s);
    n=s.size();
    for(k=1;;k++)
        dfs(n,1,(int)sqrt(n*1.0));
}

 

posted @ 2018-08-15 17:46  zzuqy  阅读(106)  评论(0编辑  收藏  举报