搜索与DP:SLIKAR

Problem: SLIKAR
【题目描述】
Josip 是个奇怪的画家,他想画一幅由 N*N 个点组成的图, N 是一个 2 的乘方 数(1, 2, 4, 8, 16 等.)。每个点要么是黑色的,要么是白色的。 Josip 画画有一个习惯。 他用下列递归的方式画画:
1.如果图像只包含一个点,他可以以任意色画(黑或白)。
2.否则,他把图分成四个大小相等的正方形部分:
3.从四个中选出一个,用白色的填充。
4.从剩余的三个中选一个,用黑色的填充。
5.把剩余的二部分重新按相同的三步进行填充。 不久以后,他发现,用他的方法并不能画出所有的画。请你编一个程序帮他设计一 个画图方案,使得用他的方法画出的画与想得到的画之间的差距最少(不同点的个 数最少)。
【输入说明】
第一行为一个整数 N (1 ≤ N ≤ 512),表示 Josip 画的图的尽寸。 N 是 2 的乘方数。 后面有 N 行,每行由 N 个 0 或 1 组成,表示画中的黑白点。
【输出说明】
输出第一行为最少可能的不同点数。
后面 N 行输出 Josip 可以画出的与目标图最接近的图。
注,第二部分的图可能不唯一。
【约定】
有 50%的点, N 最多是 8。
【样例】
input
4
1111
1111
1111
1111
output
6
0011
0011
0111
1101

这题其实暴搜就可以了,这里我建了一棵四叉树,用来处理二维的区间问题

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 using namespace std;
  5 int N,map[514][514],tot[514][514];
  6 char s[514][514];
  7 int work[15][6]={
  8     {0},
  9     {0,1,2,3,4},
 10     {0,1,2,4,3},
 11     {0,1,3,2,4},
 12     {0,1,3,4,2},
 13     {0,1,4,2,3},
 14     {0,1,4,3,2},
 15     {0,2,3,1,4},
 16     {0,2,3,4,1},
 17     {0,2,4,1,3},
 18     {0,2,4,3,1},
 19     {0,3,4,1,2},
 20     {0,3,4,2,1},
 21 };
 22 struct node{
 23     int L,R,U,D,K,sum;
 24 }tr[360010];
 25 int Q(int U,int D,int L,int R)
 26 {
 27     return tot[D][R]-tot[U-1][R]-tot[D][L-1]+tot[U-1][L-1];
 28 }
 29 int S(int U,int D,int L,int R)
 30 {
 31     return (D-U+1)*(R-L+1);
 32 }
 33 void Build(int Node,int U,int D,int L,int R)
 34 {
 35     tr[Node].L=L;tr[Node].R=R;
 36     tr[Node].U=U;tr[Node].D=D;
 37     if(L==R)return;
 38     Build(4*(Node-1)+2,U,(U+D)/2,L,(L+R)/2);
 39     Build(4*(Node-1)+3,U,(U+D)/2,(L+R)/2+1,R);
 40     Build(4*(Node-1)+4,(U+D)/2+1,D,L,(L+R)/2);
 41     Build(4*(Node-1)+5,(U+D)/2+1,D,(L+R)/2+1,R);
 42 }
 43 
 44 void Solve(int Node)
 45 {
 46     if(tr[Node].L==tr[Node].R){
 47         tr[Node].sum=0;
 48         return;
 49     }
 50     int son[5];
 51     son[1]=4*(Node-1)+2;son[2]=4*(Node-1)+3;
 52     son[3]=4*(Node-1)+4;son[4]=4*(Node-1)+5;
 53     
 54     Solve(son[1]);Solve(son[2]);
 55     Solve(son[3]);Solve(son[4]);
 56     
 57     int minn=100000000,minp;
 58     int ss=S(tr[Node].U,tr[Node].D,tr[Node].L,tr[Node].R)/4;
 59     for(int i=1;i<=12;i++)
 60     {
 61         int ret;
 62         int a=son[work[i][1]],b=son[work[i][2]];
 63         int c=son[work[i][3]],d=son[work[i][4]];
 64         ret=tr[a].sum+tr[b].sum;
 65         ret+=Q(tr[c].U,tr[c].D,tr[c].L,tr[c].R);
 66         ret+=ss-Q(tr[d].U,tr[d].D,tr[d].L,tr[d].R);
 67         if(ret<minn){
 68             minn=ret;
 69             minp=i;
 70         }
 71     }
 72     int a=son[work[minp][1]],b=son[work[minp][2]];
 73     int c=son[work[minp][3]],d=son[work[minp][4]];
 74     tr[a].K=tr[b].K=2;
 75     tr[c].K=0;tr[d].K=1;
 76     tr[Node].sum=minn;
 77     return;
 78 }
 79 
 80 void Paint(int Node)
 81 {
 82     int son[5];
 83     son[1]=4*(Node-1)+2;son[2]=4*(Node-1)+3;
 84     son[3]=4*(Node-1)+4;son[4]=4*(Node-1)+5;
 85     
 86     if(tr[Node].K==2){
 87         if(tr[Node].L==tr[Node].R)
 88             return;
 89         Paint(son[1]);Paint(son[2]);
 90         Paint(son[3]);Paint(son[4]);    
 91     }
 92     else{
 93         for(int i=tr[Node].U;i<=tr[Node].D;i++)
 94             for(int j=tr[Node].L;j<=tr[Node].R;j++)
 95                 map[i][j]=tr[Node].K;
 96     }
 97 }
 98 int main()
 99 {
100     freopen("slikar.in","r",stdin);
101     freopen("slikar.out","w",stdout);
102     scanf("%d",&N);
103     for(int i=1;i<=N;i++)scanf("%s",s[i]+1);
104     for(int i=1;i<=N;i++)
105         for(int j=1;j<=N;j++)
106         {
107             map[i][j]=s[i][j]-'0';
108             map[i][j]+=map[i][j-1];
109         }
110     
111     for(int i=1;i<=N;i++)
112         for(int j=1;j<=N;j++)
113             tot[i][j]=tot[i-1][j]+map[i][j];
114     
115     Build(1,1,N,1,N);
116     
117     Solve(1);
118     
119     for(int i=1;i<=N;i++)
120         for(int j=1;j<=N;j++)
121             map[i][j]=s[i][j]-'0';
122     
123     tr[1].K=2;
124     Paint(1);
125     
126     printf("%d
",tr[1].sum);
127     for(int i=1;i<=N;i++){
128         for(int j=1;j<=N;j++)
129             printf("%d",map[i][j]);
130         printf("
");    
131     }
132     return 0;
133 }
尽最大的努力,做最好的自己!
原文地址:https://www.cnblogs.com/TenderRun/p/5175865.html