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; }}
- poj1691(状态压缩,树型DP)
- poj1691 状态压缩~最优值
- 状态压缩dp
- pku1038状态压缩dp
- 状态压缩DP 入门
- HDU1074 状态压缩DP
- Poj3254 状态压缩DP
- 状态压缩DP入门
- 【状态压缩DP】互不侵犯
- 【状态压缩DP】电子竞技
- HDU1074 状态压缩DP
- 【状态压缩DP】互不侵犯
- 状态压缩 DP AHU420
- HDU2167 状态压缩DP
- SGU223 -状态压缩DP
- poj3254 状态压缩dp
- 状态压缩dp poj1185
- DP(2) 状态压缩
- poj 2109 : Power of Cryptography
- ExtJs4.0 TreePanel+CheckBox全选
- 众多Android 开源项目推荐,给力工作给力学习
- SQL 行列转换
- extern ,EXPORT_SYMBOL
- poj1691(状态压缩,树型DP)
- Linux文件查找命令find,xargs详述
- Log4net的使用
- 不靠谱的tooltip
- eval用法
- 外部访问JNDI容器内的JDBC数据源
- CSS进阶:详解CSS优先级的读法
- win32声音播放 和 symbain声音播放 的机制 相似
- QPBOC