您的位置:首页 > 其它

记录路径dp-4713-Permutation

2013-09-10 13:03 197 查看
题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4713

题目大意:

题意同HDU 3092这不过这题要输出路径。

解题思路:

思路同HDU 3092

因为n比较大,不能开二维只记录前面一个来 逆着存路径。

所以对于每个状态,把到达它的所有数都保存下来。转移的时候将前面的路径也赋值过来。

dp[i]表示表示不超过i的能分成的最大的最小公倍数的对数。少了的话用1来凑。

注意:输出的时候值小的在前面,+1成环输出。

代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF 0x3fffffff
#define PI acos(-1.0)
#define ll __int64
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define Maxn 10000 //三千内的质数430个

double dp[Maxn+10]; //取对数保证最小公倍数不会溢出
//dp[i]表示i能分成的最大的最小公倍数的对数
bool tmp[Maxn+10];
int pp[Maxn+10],ans[Maxn+10];
vector<int>myv[Maxn+10];

int n,cnt;

void init()
{
    cnt=0;
    memset(tmp,false,sizeof(tmp));
    for(int i=2;i<=Maxn;i++) //素数晒选法
    {
        if(!tmp[i])
        {
            pp[++cnt]=i;
            for(int j=i*2;j<=Maxn;j+=i)
                tmp[j]=true;
        }
    }
    return ;
}

void solve()
{
    memset(dp,0,sizeof(dp));
    for(int i=0;i<=n;i++)
        myv[i].clear();
    for(int i=1;i<=cnt&&pp[i]<=n;i++)
    {
        double tt=log10(pp[i]*1.0);
        for(int j=n;j>=pp[i];j--) //相同质数应做为一个整体考虑
        {
            for(int k=pp[i],num=1;k<=j;k=k*pp[i],num++)
                if(dp[j-k]+tt*num>dp[j])
                {
                    dp[j]=dp[j-k]+tt*num;
                    myv[j]=myv[j-k];
                    myv[j].push_back(k);
                }
        }
    }
}

int main()
{
    init();
    //printf("%d\n",cnt);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        solve();
        int t=myv
.size();
        int sum=0;

        for(int i=0;i<t;i++)
            sum+=myv
[i];
        sum=n-sum;
        while(sum--)
            myv
.push_back(1);
       sort(myv
.begin(),myv
.end());
        int s=0;
        for(int i=0;i<myv
.size();i++)
        {
            for(int j=1;j<myv
[i];j++)
                printf("%d ",s+j+1);
            printf("%d",s+1);
            if(i!=myv
.size()-1)
                putchar(' ');
            s+=myv
[i];
        }
        putchar('\n');
    }

    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: