ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

M - Little Pony and Harmony Chest 状压dp

2019-07-27 17:05:33  阅读:259  来源: 互联网

标签:状态 Little Pony int 质数 状压 abs include dp


M - Little Pony and Harmony Chest

 怎么感觉自己越来越傻了,都知道状态的定义了还没有推出转移方程。

首先这个a的范围是0~30   这里可以推出 b数组的范围 0~60

原因很简单,因为这个要求abs(b-a)) 尽量小,所以如果b>=60 那还不如用1 ,因为1 的数量是没有限制的,

当 b>60 abs(b-a)>30 所以相比 b>60 b==1 更优。

然后我们对质数进行状压,为什么要对质数进行状压呢,因为质数两两互质,而且每一个数都是由若干个质数组成。

所以我们可以用质数来对状态进行筛选。

因为b的范围是从1到58(如果要选59,则也可以选1),所以我们要打个表,来表示他是由哪些素数组成的。

为什么要这样呢,因为这样可以就可以快速判断出之前的状态是不是和这个有冲突(就是有没有相同的质数)

知道这些就差不多了,这个题目利用状压位运算来判断一个两两之间有没有公约数,方法很巧妙。

具体:

dp[i][s] 表示到第 i 个位置,之前的状态为 s 的最小代价,

初始化 dp[0][0]=0,其他都是不合理的状态,所以初始化为inf

首先枚举位置,其次枚举状态,然后在枚举这个位置所有可能的数。

路径的输出就是记录这个状态的放的数,和这个状态之前的状态,一个是记录状态一个是记录数。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1e5 + 10;
typedef long long ll;
ll dp[102][1<<17];
int is[102][1<<17];
int pre[102][1<<17];
int p[maxn], isp[maxn], m;
void init()
{
    memset(p, 0, sizeof(p));
    for (int i = 2; i <= 100; i++) p[i] = 1;
    for(int i=2;i*i<=100;i++)
    {
        if(p[i])
        {
            for(int j=i*i;j<=100;j+=i)
            {
                p[j] = 0;
            }
        }
    }
    m = 0;
    for(int i=1;i<=100;i++)    if (p[i]) isp[++m] = i;
}
int sta[100], a[110];
vector<int>e;
int main()
{
    int n; init();
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    for(int i=2;i<=60;i++)
    {
        for(int j=1;j<=17;j++)
        {
            if (i%isp[j] == 0) sta[i] |= (1 << (j - 1));//sta 数组表示选i这个数的限制条件,这个要好好理解。
        }
    }
    memset(pre, -1, sizeof(pre));
    memset(dp, inf64, sizeof(dp));
    dp[0][0] = 0;//这个dp定义的是到第i个位置,数的状态为s的代价,
    //如果dp == inf  说明是不合理的状态,因为如果是在0这个位置,所以当没有数的状态就是合理的而且代价==0
    for(int i=0;i<n;i++)//这个从0 开始是因为每次第i个更新第i+1个
    {
        for(int j=0;j<(1<<17);j++)
        {
            if (dp[i][j] == inf64) continue;
            for(int k=1;k<=60;k++)
            {
                if (sta[k] & j) continue;
                int tmp = sta[k] | j;
                if (dp[i + 1][tmp] > dp[i][j] + abs(a[i+1] - k))
                {
                    dp[i + 1][tmp] = dp[i][j] + abs(a[i+1] - k);
                    is[i + 1][tmp] = k;
                    pre[i + 1][tmp] = j;
                }
            }
        }
    }
    int ans=inf, id=0;
    for(int i=0;i<(1<<17);i++)
    {
        if(dp[n][i]<ans)
        {
            ans = dp[n][i];
            id = i;
        }
    }
    for(int i=n;i>=1;i--)
    {
        e.push_back(is[i][id]);
        id = pre[i][id];
    }
    for (int i = e.size() - 1; i >= 0; i--) printf("%d ", e[i]);
    printf("\n");
    return 0;
}
状压dp

 

标签:状态,Little,Pony,int,质数,状压,abs,include,dp
来源: https://www.cnblogs.com/EchoZQN/p/11255774.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有