HDU 4979: 更好的DLX模板 + 打表

来源:互联网 发布:剑网三盾太捏脸数据 编辑:程序博客网 时间:2024/06/05 23:03

本题构造矩阵并不难,用所有可能出现的组合当列,用所有可能买到的组合当行,然后跑一个可重复匹配即可……

恶心的事情在于这题数据量有点大,C84 = 70行,可重复覆盖有点吃不消。

所以应该打表……但是有几组数据真是需要跑好长时间才能跑出来,感觉是需要手算的,一组是8 3 2, 一组是8 5 4.

判断是否为1的话,我们可以用二进制判断,12345能够覆盖1234 => 11111 & 1111 == 1111这样就可以了。


嗯其实最主要的目的是修一下自己的DLX模板,之前模板为什么写得跟shi一样……


#include<iostream>#include<stdio.h>#include<string.h>#include<math.h>using namespace std; const int INF=1<<30;const int MAXNUM=5000; int u[MAXNUM], d[MAXNUM], l[MAXNUM], r[MAXNUM];//上下左右int s[MAXNUM], col[MAXNUM], row[MAXNUM];//s[i]:第i列有几个节点,即有几个1,col[i]能告诉你i这个节点在第几列,row同样struct Info // 如有需要,用这个结构体记录行列表头的附加信息{int bit_hash;};Info column_info[MAXNUM], row_info[MAXNUM];int row_selected[MAXNUM]; // 是否删过行 int head;//总表头,其实就是0号节点int p_nodes;//目前用了多少节点int column_num=0;//主程序中填写列数, 行数,也可以动态填写int row_num=0;int ans_num=0; ///////////INSERT UNIQUE THINGS HEREint n, m, k;int t;int bit_hash_idx=1;int two[10];/////////////////////////////////// void del(int c)//注意和精确模板的差别,不用动{    for(int i=d[c]; i!=c; i=d[i])    {        l[ r[i] ] = l[i];        r[ l[i] ] = r[i];        s[ col[i] ] --;    }    return;} void resume(int c)//恢复上面的操作,不用动{    for(int i=u[c]; i!=c; i=u[i])    {        s[ col[i] ] ++;        r[ l[i] ] =i;        l[ r[i] ] = i;    }      return;} int Hash() // 固定的Astar用函数,只需要修改hs下标 > 列数{    int ret=0;    int hs[100]={0};//给每列用的,所以至少要开到列数那么大    for(int c=r[head]; c!=head;c=r[c])    {        if(hs[c]==0)        {            hs[c]=1;            ret++;                         for(int i=d[c]; i!=c; i=d[i])            {                for(int j=r[i]; j!=i; j=r[j])                {                    hs[ col[j] ] =1;                }            }        }    }    return ret;} void DFS(int depth, int cost) //基本不用动,看看是否需要记录答案等就可以了{    ////TEST    //cout<<depth<<endl;    if(depth-1 + Hash() > row_num)        return;    if(cost >= ans_num)        return;         if(r[head] == head)    {        ans_num=min(cost, ans_num);        return;//矩阵被删干净了    }         int min1=INF, now;//挑一个1数最少列的先删    for(int t=r[head]; t!=head; t=r[t])    {        if(s[t]==0)            return;        if(s[t] <=min1 )        {            min1=s[t];            now=t;        }    }    //TEST    //cout<<"now: "<<now<<endl;         int i, j;    for(i=u[now]; i!=now; i=u[i])    {        del(i);        //↑注意和精确模板的差别        //枚举这一列每个1由哪行来贡献,这行即为暂时性的答案,//如果需记录都删了哪些行,此时记录ans[depth]=row[i]就可以了int now_ans = row[i];row_selected[now_ans]++;if(row_selected[now_ans]==1)cost++;        ///TEST        //cout<<"ans[depth]: "<<ans[depth]<<endl;        for(j=r[i]; j!=i; j=r[j])        {            del(j);        }                 DFS(depth+1, cost);                 for(j=l[i]; j!=i; j=l[j])        {            resume(j);        }row_selected[now_ans]--;        if(row_selected[now_ans]==0)            cost--;                 resume(i);    }     return;} void init(){    memset(u,0,sizeof(u));    memset(d,0,sizeof(d));    memset(l,0,sizeof(l));    memset(r,0,sizeof(r));    memset(s,0,sizeof(s));    memset(col,0,sizeof(col));memset(row,0, sizeof(row));memset(column_info, 0, sizeof(column_info));memset(row_info, 0, sizeof(row_info));     head=0;    p_nodes=0;         //INSERT UNIQUE THINGS HEREbit_hash_idx = 1;ans_num = INF;return;} int insert_node(int row_first1, int j, int now_row)//知道我当前的行第一个是谁,我在第j列, 第now_row行,基本不用动{    p_nodes++;    s[j] ++;    u[p_nodes] = u[j];    d[ u[j] ] = p_nodes;    u[j] = p_nodes;    d[p_nodes] = j;             col[p_nodes] = j;//和列的关系处理完毕             if(row_first1==-1)    {        l[p_nodes] = r[p_nodes] = p_nodes;        row_first1=p_nodes;    }    else    {        l[p_nodes] = l[row_first1];        r[ l[row_first1] ] = p_nodes;        r[p_nodes] = row_first1;        l[ row_first1 ]=p_nodes;//和行的关系处理完毕    }    row[p_nodes]=now_row;    return row_first1;     } void insert_row(int idx)//新建一行,一行里会插入若干结点,idx = 这是第几行{    int row_first1=-1;//看看这一行是不是已经有第一个1了         int i;    for(i=1; i<=column_num; i++)    {if( (row_info[idx].bit_hash & column_info[i].bit_hash ) == column_info[i].bit_hash) //是1的条件row_first1=insert_node(row_first1, i, idx);    }    return;} void InitLinks()//注意:该链表两个方向都是循环的,最上面的上面指最下面{    int i;    r[head]=1;    l[head]=column_num;         for(i=1;i<=column_num;i++)//制作列的表头,使用结点1~column_num    {        l[i]=i-1;        r[i]=i+1;        if(i==column_num)            r[i]=head;        u[i]=i;        d[i]=i;        s[i]=0;        col[i]=i;//如有需要,在这里填写列表头的Info,由于已经填写完了就不填写了    }         p_nodes=column_num;    for(i=1; i<=row_num; i++)    {        insert_row(i);//可以在这里填写行表头info    }}void GenerateBit(int now, int now_value, int max_length, Info target[], int pre, int max_idx)//本题特有的填写行列表头函数{if(now == max_length+1){target[bit_hash_idx].bit_hash = now_value;bit_hash_idx++;return;}int i;for(i=pre+1;i<=n;i++){now_value += two[i-1];GenerateBit(now+1, now_value, max_length, target, i, max_idx);now_value -= two[i-1];if(bit_hash_idx > max_idx)return;}return;}int C(int x, int y){int i;int up=1, down = 1;for(i=1; i<=y; i++)up*=x+1-i;for(i=y; i>=1; i--)down *= i;return up/down;} int main(){//freopen("1.txt", "w", stdout);ofstream fout("1.txt");two[0]=1;for(int tmp=1;tmp<=9;tmp++)two[tmp] = 2*two[tmp-1];    scanf("%d", &t);    for(int files=1; files<=t; files++)    {scanf("%d %d %d", &n, &m, &k);        column_num=C(n, k);row_num = C(n, m);GenerateBit(1, 0, k, column_info, 0, column_num);bit_hash_idx = 1;GenerateBit(1, 0, m, row_info, 0, row_num);        InitLinks();        DFS(1,0);        printf("Case #%d: ", files);cout<<ans_num<<", ";    }    system("pause");    return 0;}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 刚买的笔记本c盘不足怎么办 qq糖粘在喉咙气管里怎么办 穿上旗袍后感觉后腰处不平整怎么办 机打票给客人给错联怎么办?急 ps修证件照感觉不太立体怎么办 手机百度上下载的文档打不开怎么办 5岁宝宝乘飞机没带证件怎么办 网上订飞机票忘记订儿童票了怎么办 两岁宝宝对牛奶鸡蛋过敏了怎么办 两岁宝宝坐不住好跑怎么办 宝宝两岁多了不愿意坐小马桶怎么办 坐火车小孩拉屎在被子上怎么办 川航飞机票名字错了一个字怎么办 胜战本领怎么看走向战场怎么办 数数字油画你的颜料干了怎么办? 数字油画涂颜料涂错了怎么办 绝地求生模拟器注册已达上限怎么办 孕妇把番茄和虾一起吃了怎么办 4岁宝贝吃了玩具小电池怎么办 微信使用零钱需完善实名信息怎么办 两岁宝宝刷牙不会吐水怎么办 孩子牙龈上长了小牙怎么办 供暖公司未供暖却收取供暖费怎么办 两岁宝宝认知和语言能力低怎么办 蜡笔同步被对方发现删掉的怎么办 微信时间和手机时间不同步怎么办 孩子们家乡爱画美丽的也自己怎么办 娃把豆豆弄进鼻孔了怎么办 20岁了不知道自己该干什么怎么办 遇到一个新手买家恶意拍下怎么办 淘宝卖螃蟹有什么要求美工怎么办 淘宝衣服吊牌剪了想退货怎么办修 用图片在淘宝搜衣服搜不到怎么办 汽车黑塑料水砂纸磨的不平怎么办 sat报名要你填10位电话怎么办 手绘板连接电脑绘画有点迟钝怎么办 走路不小心滑了一下特尴尬怎么办 小孩子头撞了头发长不出来怎么办 小孩子头磕破了不长头发怎么办 晚上洗了冷水头早上头痛怎么办 头发洗了一天就油了怎么办