题目来源
题干
解释
本解释为个人的拙劣思路,不代表官方思路(个人认为还可以优化)
因为要保证每个被分割的方格里的方块都是颜色相隔的,最小的子方格情形只有两种
三个一组的子方格-S3 两个一组的子方格-S2
在n行m列的方格中,因为我们无法判断一个动态问题
所以我们都会计算一遍让n和m分别作为行和列进行最小值判断
单行填入函数
首先介绍一下单行填入函数
如果x(列数)为3的倍数,则直接填入x/3个S3
如果余一,则填入X/3-1个S3,再加一个S2
如果余二 ,则填入X/3个S3,再加一个S2
插入规则
总是先将 S3 竖着放入方格
假设LINE正好是的3的倍数,则最小这么填入
假设LINE是3的倍数余1
这时只需要横过来填入最后一行就可以啦(按照单行填入函数)
假设LINE是3的倍数余2
这时易证一个结论如果横过来填入S3与S2会比竖着填入S2要小
ROW列数为Y,则竖过来填入S2需要S2*Y,横过来则按照单行填入函数进行
Y为3的倍数,S2*Y>Y/3*2
Y不为3的倍数,S2*Y>([Y/3]+1)*2;(当Y为1的时候虽然这时候计算会不满足,当交换行列数m,n之后,仍旧能取到正确的最小值)
代码段
int num2(int x)
{
int num2=0;
if (x % 3 == 1)num2 = x / 3 -1+2;
if (x % 3 == 2)num2 = x / 3 + 1;
if (x % 3 == 0)num2 = x / 3;
return num2;
}
int num(int x,int y)
{
int num1=0;
if (x % 3 == 1)num1 = x /3*y+num2(y);
if (x % 3 == 2)num1 = (x / 3 )*y+num2(y)*2;
if (x % 3 == 0)num1= x / 3*y;
return num1;
}
void solve()
{
int n, m;
cin >> n>>m;
int ans = min(num(m,n),num(n,m));
cout << ans << endl;
}