hdu3663Power Stations(DLX解精确覆盖)

题目请戳这里

题目大意:一个国家有n个城市,每个城市有一个电站。n个城市之间有m条电线,通过电线相连的城市之间可以互相通电。现在给出每个城市发电站工作的时间段,要求使所有的城市在未来连续D小时都通电并且保证每个城市只能同时接受一个城市的电(或者自己发电),求每个城市发电站工作时间表,每个城市只能工作一个连续的时间段。

题目分析:点支配集转精确覆盖问题,DLX解决。由于所有城市在未来连续D小时都必须通电。所以每个城市抽象出D列,一共n*D列。对于每个城市,由于工作的时间段长度不超过5。所以每个城市发电站工作的时间段最多15种情况。所以每个城市抽象出15行,一共n*15行。然后根据城市之间的连线情况建图,跑DLX算法即可。

对于每个城市发电站工作的时间段,一共15种情况,每种情况对应一个id,用一个二维数组保存。因为每个城市只能工作一个连续的时间段,那么在搜索过程中要进行判重。

详情请见代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;
const int N = 61;
const int M = N * 15 * 6 * N + 10;

int n,m,D;
int s[M],h[M],u[M],d[M],l[M],r[M],col[M],row[M],ans[M],aans[N][3];
int num;
bool flag[N][N];
map<int,int>lcm;
bool vis[N];
bool ok;
int idx[6][6] = {
    {0,0,0,0,0,0},
    {0,1,0,0,0,0},
    {0,2,6,0,0,0},
    {0,3,7,10,0,0},
    {0,4,8,11,13,0},
    {0,5,9,12,14,15},
};
void init()
{
    int i,c;
    memset(h,0,sizeof(h));
    memset(s,0,sizeof(s));
    memset(vis,false,sizeof(vis));
    memset(flag,false,sizeof(flag));
    c = D * n;
    for(i = 0;i <= c;i ++)
    {
        u[i] = d[i] = i;
        l[i] = (i + c) % (c + 1);
        r[i] = (i + 1) % (c + 1);
    }
    num = c + 1;
    lcm.clear();
    lcm[1] = 11;
    lcm[2] = 12;lcm[6] = 22;
    lcm[3] = 13;lcm[7] = 23;lcm[10] = 33;
    lcm[4] = 14;lcm[8] = 24;lcm[11] = 34;lcm[13] = 44;
    lcm[5] = 15;lcm[9] = 25;lcm[12] = 35;lcm[14] = 45;lcm[15] = 55;
}
void insert(int i,int j)
{
    if(h[i])
    {
        r[num] = h[i];
        l[num] = l[h[i]];
        l[r[num]] = num;
        r[l[num]] = num;
    }
    else
        h[i] = l[num] = r[num] = num;
    s[j] ++;
    u[num] = u[j];
    d[num] = j;
    d[u[j]] = num;
    u[j] = num;
    col[num] = j;
    row[num] = i;
    num ++;
}
void remove(int x)
{
    int i,j;
    l[r[x]] = l[x];
    r[l[x]] = r[x];
    for(i = d[x];i != x;i = d[i])
        for(j = r[i];j != i;j = r[j])
        {
            u[d[j]] = u[j];
            d[u[j]] = d[j];
            s[col[j]] --;
        }
}
void resume(int x)
{
    int i,j;
    for(i = u[x];i != x;i = u[i])
        for(j = l[i];j != i;j = l[j])
        {
            s[col[j]] ++;
            u[d[j]] = d[u[j]] = j;
        }
    l[r[x]] = r[l[x]] = x;
}
void dfs(int k)
{
    if(ok)
        return;
    int i,j;
    if(!r[0])
    {
        ok = true;
        memset(aans,0,sizeof(aans));
        for(i = 0;i < k;i ++)
        {
            int ii = (ans[i] - 1)/15 + 1;
            int jj = ans[i] - (ii - 1) * 15;
            aans[ii][0] = lcm[jj]/10;
            aans[ii][1] = lcm[jj]%10;
        }
        for(i = 1;i <= n;i ++)
            printf("%d %d\n",aans[i][0],aans[i][1]);
        return;
    }
    int mx = M;
    int c;
    for(i = r[0];i;i = r[i])
    {
        if(s[i] < mx)
        {
            mx = s[i];
            c = i;
        }
    }
    remove(c);
    int tmp;
    for(i = d[c];i != c;i = d[i])
    {
        tmp = (row[i] - 1)/15 + 1;//判重
        if(vis[tmp] == true)
            continue;
        vis[tmp] = true;
        ans[k] = row[i];
        for(j = r[i];j != i;j = r[j])
            remove(col[j]);
        dfs(k + 1);
        if(ok)
            return;
        for(j = l[i];j != i;j = l[j])
            resume(col[j]);
        vis[tmp] = false;
    }
    resume(c);
}
int main()
{
    int a,b,i,j,ii,jj,st,ed;
    while(scanf("%d",&n) != EOF)
    {
        scanf("%d%d",&m,&D);
        init();
        while(m --)
        {
            scanf("%d%d",&a,&b);
            flag[a][b] = flag[b][a] = true;
        }
        for(i = 1;i <= n;i ++)//可以给自己供电
            flag[i][i] = true;
        for(i = 1;i <= n;i ++)//建图
        {
            scanf("%d%d",&st,&ed);
            int base = (i - 1) * 15;
            for(ii = st;ii <= ed;ii ++)//可能的时间段
            {
                for(jj = st;jj <= ii;jj ++)
                {
                    for(j = 1;j <= n;j ++)//i可以供电的城市
                        if(flag[i][j] == true)
                        {
                            for(int ai = jj;ai <= ii;ai ++)
                                insert(base + idx[ii][jj],(j - 1) * D + ai);
                        }
                }
            }
        }
        ok = false;
        dfs(0);
        if(ok == false)
            puts("No solution");
        puts("");
    }
    return 0;
}


你可能感兴趣的:(搜索)