P1283 平板涂色

数据范围也太小了qwq。。适合本萌新暴搜

小小的剪枝:

1.用pre预处理出每块矩形上方的矩形,pre[i][0]记录数目(如果数据范围再开大一点,直接1~n枚举判断可能超时qwq)

2.每次对于可以涂的矩形,颜色相同的直接标记涂上,不同的dfs(而不用全都dfs)

#include
#include
using namespace std;
int n,ans;
int x[17],y[17],xx[17],yy[17],c[17],pre[17][17];
bool vis[17];
inline bool chk(int i) {//检查上方的矩形是否都涂过
    for (int j=1; j<=pre[i][0]; j++)
        if (!vis[pre[i][j]])
            return false;
    return true;
}
inline void dfs(int step,int num,int co) {//step拿起刷子的最少次数,num涂过的矩形数,co当前颜色
    if (step>=ans) return;
    for (int i=1; i<=n; i++)//每次把能涂的尽量涂好
        if (!vis[i] && chk(i) && c[i]==co)
            vis[i]=1,++num;
    if (num==n) {
        if (ans>step) ans=step;
        return;
    }
    for (int i=1; i<=n; i++)//寻找颜色不同但可以涂的继续dfs
        if (!vis[i] && chk(i)) dfs(step+1,num,c[i]);
}
int main() {
    scanf("%d",&n),ans=n;
    for (int i=1; i<=n; i++)
            scanf("%d%d%d%d%d",&y[i],&x[i],&yy[i],&xx[i],&c[i]);
    for (int i=1; i<=n; i++)
        for (int j=1; j<=n; j++)
            if (i^j && yy[i]==y[j])//如果两块矩形不是同一个,且上下贴合
                if (x[i]=xx[j]) {
                    pre[j][pre[j][0]=1]=i;
                    break;//如果上矩形覆盖了下矩形的整条边
                } else if ((x[i]=x[j]) || (xx[i]=x[j]))//如果覆盖了一部分
                    pre[j][++pre[j][0]]=i;
    for ( int a=1; a<=n ;a++)
        if (!pre[a][0]) memset(vis,0,sizeof vis),vis[a]=1,dfs(1,1,c[a]);//每次寻找可以涂的开始dfs
    printf("%d",ans);
}