[kuangbin]专题三 Dancing Links Divisibility HDU - 3335【重复覆盖】

【题目描述】
As we know,the fzu AekdyCoin is famous of math,especially in the field of number theory.So,many people call him “the descendant of Chen Jingrun”,which brings him a good reputation.
据我所知,the fzu AekdyCoin以数学出名,特别是在数论领域。所以很多人叫他"the descendant of Chen Jingrun"。
AekdyCoin also plays an important role in the ACM_DIY group,many people always ask him questions about number theory.One day,all members urged him to conduct a lesson in the group.The rookie daizhenyang is extremely weak at math,so he is delighted.
AekdyCoin在ACM_DIY群中扮演着重要的角色,很多人总是问他关于数论的问题。有一天,所有人都希望他在群里上课。菜鸟daizhenyang数学非常薄弱,所以他很高兴。
However,when AekdyCoin tells us “As we know, some numbers have interesting property. For example, any even number has the property that could be divided by 2.”,daizhenyang got confused,for he don’t have the concept of divisibility.He asks other people for help,first,he randomizely writes some positive integer numbers,then you have to pick some numbers from the group,the only constraint is that if you choose number a,you can’t choose a number divides a or a number divided by a.(to illustrate the concept of divisibility),and you have to choose as many numbers as you can.
但是,当AekdyCoin告诉我们“如我们所知,有些数字具有有趣的性质。例如,任何偶数都具有可除以2的属性”,daizhenyang感到十分困惑了,因为他没有可除性的概念。他向其他人求助,首先,他随机地写了一些正整数,然后你需要从中挑选一些数字,唯一的限制是,如果选择数字a,则不能选择一个数字除以a或一个数字被a除(用来说明可除性的概念),你必须选择尽可能多的数字。
Poor daizhenyang does well in neither math nor programming.The responsibility comes to you!
daizhenyang既不擅长数学,也不擅长编程。责任就在你身上!

【输入】
An integer t,indicating the number of testcases,
For every case, first a number n indicating daizhenyang has writen n numbers(n<=1000),then n numbers,all in the range of (1…2^63-1).
一个整数t,表示测试样例的个数。
对于所有样例,第一个数字n表示daizhenyang写下n个数,(n<=1000),然后n个数字,都在1…2^63-1的范围内。

【输出】
The most number you can choose.
你可以选择的最多的数字。

【样例输入】
1
3
1 2 3

【样例输出】
2

【样例提示】
If we choose 2 and 3,one is not divisible by the other,which is the most number you can choose.
如果我们选择2和3,一个都不能被其他的整除,这是你能选择的最多的数字。

题目链接:https://cn.vjudge.net/problem/HDU-3335

一开始一直觉得是精确覆盖问题,后来发现是重复覆盖

代码如下:

#include <iostream>
using namespace std;
typedef long long ll;
static const int MAXM=1000+10;
static const int MAXN=1000+10;
static const int MAXNODE=MAXN*MAXM;
ll a[MAXM];
struct DLX{
    int n,m,size;
    int U[MAXNODE],D[MAXNODE],R[MAXNODE],L[MAXNODE],Row[MAXNODE],Col[MAXNODE];
    int H[MAXN],S[MAXM];
    int ansd,ans[MAXN];
    bool vis[MAXNODE];
    void init(int _n,int _m)
    {
        n=_n;
        m=_m;
        for(int i=0;i<=m;i++)
        {
            S[i]=0;
            U[i]=D[i]=i;
            L[i]=i-1;
            R[i]=i+1;
        }
        R[m]=0;
        L[0]=m;
        size=m;
        for(int i=1;i<=n;i++)
            H[i]=-1;
    }
    void Link(int r,int c)
    {
        ++S[Col[++size]=c];
        Row[size]=r;
        D[size]=D[c];
        U[D[c]]=size;
        U[size]=c;
        D[c]=size;
        if(H[r]<0)
            H[r]=L[size]=R[size]=size;
        else
        {
            R[size]=R[H[r]];
            L[R[H[r]]]=size;
            L[size]=H[r];
            R[H[r]]=size;
        }
    }
    void remove(int c)
    {
        for(int i=D[c];i!=c;i=D[i])
        {
            L[R[i]]=L[i];
            R[L[i]]=R[i];
        }
    }
    void resume(int c)
    {
        for(int i=U[c];i!=c;i=U[i])
            L[R[i]]=R[L[i]]=i;
    }
    int f()
    {
        int res=0;
        for(int i=R[0];i!=0;i=R[i])
            vis[i]=true;
        for(int i=R[0];i!=0;i=R[i])
            if(vis[i])
            {
                res++;
                vis[i]=false;
                for(int j=D[i];j!=i;j=D[j])
                    for(int t=R[j];t!=j;t=R[t])
                        vis[Col[t]]=false;
            }
        return res;
    }
    void Dance(int d)
    {
        if(d+f()<=ansd)
            return;
        if(R[0]==0)
        {
            if(d>ansd)
                ansd=d;
            return;
        }
        int c=R[0];
        for(int i=R[0];i!=0;i=R[i])
            if(S[i]<S[c])
                c=i;
        for(int i=D[c];i!=c;i=D[i])
        {
            remove(i);
            for(int j=R[i];j!=i;j=R[j])
                remove(j);
            Dance(d+1);
            for(int j=L[i];j!=i;j=L[j])
                resume(j);
            resume(i);
        }
        return;
    }
};
DLX dlx;
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0),cout.tie(0);
    int T;
    cin>>T;
    while(T--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        dlx.init(n,n);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(a[i]%a[j]==0 || a[j]%a[i]==0)
                    dlx.Link(i,j);
        dlx.ansd=0;
        dlx.Dance(0);
        cout<<dlx.ansd<<endl;
    }
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值