poj1691(状态压缩,树型DP)

来源:互联网 发布:急需网络兼职工作 编辑:程序博客网 时间:2024/05/17 00:56

1.先说下我自己的思路:根据题目的特点:题目要求先刷上方的矩形,因此可以用图结构来描述这种约束,若A在B的下方,则连接A到B的有向边。然后可以把当前可以刷的最上层的顶点做为状态curState,times[curState]表示在状态curState下的最少刷的次数,则在状态curState下可以有多种决策,可以用选不同颜色的矩形刷(当然选择了一种颜色后就尽可能的多刷),当然最上层的顶点可能有相同颜色的顶点,这时可以同时刷。记取种i种颜色刷后的状态为nextState[i],则状态方程可表示为times[curState]=min { times[ nextState[i] ] }+1;


2.其实还有一种更好的思路(队友想出的),时间和空间都应该要少一些。和我的相反,它用的是bfs+状态压缩+记忆化。思路是这样的,用当前染色情况作为状态,每次从队列里弹出一个状态,重新构图(当然我我DFS也是要构图的)对颜色循环,选择入度为0的进行染色,得到下一状态。(按照黑书上说的话:他的是递推的,而我的是递归的)。而这个题是刚好满足bfs性质的,第一次到达该状态的肯定是最短的路径,也就是最少的步数,因为第一次到达全部染色的状态时就直接退出。


3.自己思路的代码(刚开始时写得很顺后来发现了致命的错误,就是染色会破坏图的结构,准确的讲是入度与出度。后来终于找到了之前认为不可行的方案,在递归里开数组,每次都重新构图,自己以为是会超内存的,结果也还好才880K,0MS.不过建议大家用第二种思路写。毕竟学习得法的目地就是为了提高时空效率,简化问题。


#include<cstring>#include<cmath>#include<cstdio>#include<iostream>using namespace std;//   freopen("data.in","r",stdin);#define N 15#define STATE 32770//int times[STATE];bool mat[N][N];int color[N];struct Rect{    int x1,y1,x2,y2;} rect[N];int n;struct Node{    int vex;    Node *next;    Node(int v):vex(v),next(NULL) {}    void add(int v)    {        Node *pre,*cur;        for(pre=this,cur=next; cur!=NULL; pre=cur,cur=cur->next)        {            if(cur->vex==v)return;        }         pre->next=new Node(v);    }};void createGraph(int *in,int *out){    cin>>n;    for(int i=0; i<n; i++)    {        cin>>rect[i].y1>>rect[i].x1>>rect[i].y2>>rect[i].x2>>color[i];    }    for(int i=0;i<n;i++)in[i]=out[i]=0;//    memset(mat,0,sizeof(mat));    for(int i=0; i<n; i++)    {        for(int j=0; j<n; j++)        {            if(j!=i)            {                bool c1=rect[i].y2==rect[j].y1&&rect[i].y1<rect[j].y1;                bool c2=rect[i].x1>rect[j].x1&&rect[i].x1<rect[j].x2;                bool c3=rect[i].x2>rect[j].x1&&rect[i].x2<rect[j].x2;                bool c4=rect[i].x1<=rect[j].x1&&rect[i].x2>=rect[j].x2;//                if(c1&&(c2||c3||c4))                {                    mat[i][j]=true;                    out[i]++;                    in[j]++;                }            }        }    }}void rebuild(int u,int *in,int *out){    for(int i=0; i<n; i++)    {        if(mat[u][i])        {            out[u]++,in[i]++;            rebuild(i,in,out);        }    }}int traverse(int u,int *tIn,int *tOut){    int state=0;    for(int i=0; i<n; i++)    {        if(mat[u][i])        {            tOut[u]--;            tIn[i]--;            if(color[i]==color[u])            {                if(!tIn[i])state|=traverse(i,tIn,tOut);            }            else            {                if(!tIn[i])state|=(1<<i);            }        }    }    return state;}int dfs(int curState)//!!end{    if(times[curState]<N)return times[curState];    else    {        int tmpState=curState,node=0;        Node *yes=new Node(-1);        Node *nodes=new Node(-1);        while(tmpState)        {            if(tmpState&1)//            {                (* yes).add(color[node]);                (*nodes).add(node);            }            tmpState>>=1;            node++;        }        int in[N],out[N];        memset(in,0,sizeof(in));        memset(out,0,sizeof(out));        for(Node *tNode=nodes->next; tNode!=NULL; tNode=tNode->next)        {            rebuild(tNode->vex,in,out);        }        int tIn[N],tOut[N];//        for(Node *tColor=yes->next; tColor!=NULL; tColor=tColor->next)        {            memcpy(tIn,in,n*sizeof(int));//            memcpy(tOut,out,n*sizeof(int));            int nextState=curState;            for(Node *tNode=nodes->next; tNode!=NULL; tNode=tNode->next)            {                if(color[tNode->vex]==tColor->vex)                {                    nextState^=(1<<tNode->vex);                    nextState|=traverse(tNode->vex,tIn,tOut);                }            }            times[curState]=min(times[curState],dfs(nextState)+1);        }        return times[curState];    }}int main(){    int in[N],out[N]; //   freopen("data.in","r",stdin);    int Case;    cin>>Case;    while(Case--)    {        createGraph(in,out);        fill(times,times+STATE,N+1);//        times[0]=0;        int state=0;        for(int i=0; i<n; i++)        {            if(in[i]==0)state+=(1<<i);            if(out[i]==0)times[1<<i]=1;//        }        dfs(state);        cout<<times[state]<<endl;    }}