pku 1691 Painting A Board(据说可以用状态压缩DP)

用的搜索。

先转换成有向图,如果矩形i在矩形j的上面且两个矩形挨着,就在节点i和节点j之间连一条边。

剩下的就是搜索了,有点像拓扑排序。

#include <vector> #include <iostream> #define _clr(a,b) memset(a,b,sizeof(a)) using namespace std; int N; struct rec { int left_x,left_y,right_x,right_y,color; }recs[16]; vector<int> edges[15]; int degree[15]; bool used[15]; bool is_above(int i,int j) { if(recs[i].right_y!=recs[j].left_y) return false; if(recs[i].right_x<=recs[j].left_x||recs[i].left_x>=recs[j].right_x) return false; return true; } int DFS(int last_color,int cnt) { int ans=100; for(int i=0;i<N;i++) { if(degree[i]==0&&!used[i]) { used[i]=true; if(recs[i].color!=last_color) cnt++; for(int j=0;j<edges[i].size();j++) degree[edges[i][j]]--; int tmp=DFS(recs[i].color,cnt); if(tmp<ans) ans=tmp; for(int j=0;j<edges[i].size();j++) degree[edges[i][j]]++; used[i]=false; if(recs[i].color!=last_color) cnt--; } } if(ans==100) ans=cnt; return ans; } int main() { int T; scanf("%d",&T); for(int t=1;t<=T;t++) { _clr(degree,0); _clr(used,0); scanf("%d",&N); for(int i=0;i<N;i++) scanf("%d%d%d%d%d",&recs[i].left_y,&recs[i].left_x,&recs[i].right_y,&recs[i].right_x,&recs[i].color); for(int i=0;i<N;i++) { edges[i].clear(); for(int j=0;j<N;j++) { if(is_above(i,j)) { edges[i].push_back(j); degree[j]++; } } } printf("%d/n",DFS(-1,0)); } return 0; }

你可能感兴趣的:(pku 1691 Painting A Board(据说可以用状态压缩DP))