着色

22 篇文章 1 订阅

题目

 Alice是一个奇怪的画家。她想对一副有N*N个像素点组成的画进行着色,N是2的幂(1,2,4,8,16等等)。每个像素点可以着成黑色或白色。
  Alice着色方案不是唯一的,她采用以下不确定的规则:
  •如果画作只有一个像素点,那可以直接着白色或黑色;
  •否则,把画平均分成四块,然后进行以下操作:
  (1) 选择一块全部着白色;
  (2) 选择一块全部着黑色;
  (3) 把剩下的两块当作是独立的画作并采用同样的方法进行着色。
  对于每一幅画作,Alice心目中已经有一个蓝图,接下来请你帮她采用上述方法着色,要求选择跟心目中的蓝图差异最小的着色方案,当然要遵循上述的着色规则,两幅图的差异是指对应位置颜色不相同的像素点的个数。

分析

考虑dp,
定义 fi,j,k,l0<=k<=log2n ,表示对于一个矩阵,左上角的点是 (i,j) ,大小为 2k2 ,矩阵类型 l (0表示全为白色的不同原图的个数,1表示全为黑色的不同原图的个数,2表示这个矩阵的最优着色方案)。
显然,答案就是f1,1,log2n,2
那么转移也显然

fi,j,k,0=fi,j,k1,0+fi+2k1,j,k1,0+fi,j+2k1,k1,0+fi+2k1,j+2k1,k1,0

fi,j,k,1=fi,j,k1,1+fi+2k1,j,k1,1+fi,j+2k1,k1,1+fi+2k1,j+2k1,k1,1

fi,j,k,2=fi,j,k1,a+fi+2k1,j,k1,b+fi,j+2k1,k1,c+fi+2k1,j+2k1,k1,d

其中 abcd 中,一个是0,一个是1,剩余的两个是2。

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const int maxlongint=2147483647;
const int mo=1000000007;
const int N=515;
using namespace std;
int a[N][N],n,m,f[N][N][11][3],mi[20],z[4][2]
={{1,0},{0,0},{0,1},{1,1}};
int i,j,k;
int solve(int p,int q,int p1,int q1)
{
    int t;
    p-=1;
    p1-=1;
    q1-=1;
    q-=1;
    t=f[i+mi[k-1]*z[p][0]][j+mi[k-1]*z[p][1]][k-1][0]+
    f[i+mi[k-1]*z[p1][0]][j+mi[k-1]*z[p1][1]][k-1][1]+
    f[i+mi[k-1]*z[q][0]][j+mi[k-1]*z[q][1]][k-1][2]+
    f[i+mi[k-1]*z[q1][0]][j+mi[k-1]*z[q1][1]][k-1][2];
    if(t<f[i][j][k][2]) f[i][j][k][2]=t;
}
int main()
{
    memset(f,43,sizeof(f));
    mi[0]=1;
    for(i=1;i<=15;i++)
        mi[i]=mi[i-1]*2;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
        {
            char c;
            c=getchar();
            while(c!='1' && c!='0') 
                c=getchar();
            a[i][j]=c-48;
            f[i][j][0][0]=a[i][j];
            f[i][j][0][1]=1-a[i][j];
            f[i][j][0][2]=0;
        }
    int lo=log2(n);
    for(k=1;k<=lo;k++)
    {
        for(i=1;i<=n-mi[k]+1;i++)
            for(j=1;j<=n-mi[k]+1;j++)
            {
                f[i][j][k][0]=f[i][j][k-1][0]+f[i+mi[k-1]][j][k-1][0]+f[i][j+mi[k-1]][k-1][0]+f[i+mi[k-1]][j+mi[k-1]][k-1][0];
                f[i][j][k][1]=f[i][j][k-1][1]+f[i+mi[k-1]][j][k-1][1]+f[i][j+mi[k-1]][k-1][1]+f[i+mi[k-1]][j+mi[k-1]][k-1][1];
                solve(1,2,3,4);
                solve(1,2,4,3);
                solve(1,3,2,4);
                solve(2,1,3,4);
                solve(2,1,4,3);
                solve(2,3,1,4);
                solve(3,1,2,4);
                solve(3,1,4,2);
                solve(3,4,1,2);
                solve(4,1,2,3);
                solve(4,1,3,2);
                solve(4,2,1,3);
            }
    }
    printf("%d",f[1][1][lo][2]);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Gouraud 着色是一个在 OpenGL 图形渲染中常用的技术。它是由 Henri Gouraud 在20世纪70年代提出的,用于计算并插值多边形的表面颜色。 在OpenGL中,多边形表面的着色是通过为每个顶点指定颜色,并利用 Gouraud 着色算法在顶点之间进行插值来实现的。这样,每个顶点都有一个颜色值,而在顶点之间,颜色会平滑地渐变。 Gouraud 着色的核心思想是对每个顶点进行逐顶点着色计算,计算得到每个顶点的颜色。然后,沿着多边形的边缘线段上进行线性插值,确定每个片段的颜色。最后,根据每个片段得到的颜色信息来细化多边形表面的颜色。 Gouraud 着色具有以下优点:首先,它处理效率高,因为只需要在每个顶点上计算并插值颜色值,而不需要对每个像素进行计算。其次,它可以平滑地渐变多边形的颜色,使得表面看起来更加真实。此外,Gouraud 着色还可以应用于不同光源的场景中,使得图像更加逼真。 然而,Gouraud 着色也存在一些限制。最主要的是,它在处理锐利边缘和阴影效果时表现不佳。由于颜色插值是在顶点之间进行的,因此当有锐利的边缘或明暗转折时,插值效果可能不够精细,导致视觉上的不连续性。 总的来说,Gouraud 着色是一种简单且高效的多边形着色算法。它通过在顶点之间进行颜色插值来平滑多边形的颜色,并在 OpenGL 渲染中得到广泛应用。对于表面光滑、真实感较强的图形渲染需求,Gouraud 着色可以提供良好的视觉效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值