Codejam之Alphabet Cake

2024-02-17 18:08
文章标签 alphabet cake codejam

本文主要是介绍Codejam之Alphabet Cake,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

问题描述

需要为party准备一个蛋糕,R行 C列的格子形状。助理已经把每个孩子的名字首字母写在了蛋糕的单元里,每个孩子的名字首字母都是唯一的,没有重复。每个单元至多有1个首字母。

切分蛋糕时,每个孩子的蛋糕都是矩形的,只包含自己的名字首字母,且不包含其他孩子的名字首字母。

输入:第一行的数字T,有T个测试用例。
每个测试用例开始是R和C,接着R行,每行有C个字符,表示开始的蛋糕状况。?号表示这个单元为空,英文字母表示助理在这个单元上写的孩子名字。

输出:蛋糕的切分情况,每个单元上的字母表示分给哪个孩子。每个孩子被分得的区域必须是矩形。
不能添加新的字母
如果有多个答案,输出其中任意一个都可以。

小数据集:1<=R<=12,1<=C<=12,R*C<=12
大数据集:1<=R<=25,1<=C<=25

这里写图片描述

问题解决

一开始的想法是遍历数组,如果cake i j 等于?,向右找第一个不等于?的字母,如果没有向上找,如果没有向左或下找。
这种方法得到的可能不是矩形。

??
?E
C?

得到

CC
EE
CE

遍历数组,如果cake i j不等于?,将它当作1by1的box,先上下拉伸,再左右拉伸,不能碰到其他字母。这种方法也可能失败。
如下面这个示例,结果有一个单元没有被填充。

A?B
C??
??D
?EF

得到

AAB
C?B
CDD
CEF

暴力法

小数据集中,一个蛋糕最多有12个单元,输入的蛋糕上有L个字母,已经占据了L个单元,那么还剩下12-L个单元。对每一个空白单元,有L个字母可以选择。

情况有L的(12-L)次方种,L在1到12之间,因此最大值是5的7次方=78125

对于每种情况进行检查,检查如下:
遍历数组,找到每个字母的最左上的位置和最右下的位置,出现次数。对每个字母,检查最左上位置和最右下位置构成的矩形是否只包含这个字母,且区域的大小等于出现次数。

分治法

如果一个蛋糕上只有一个字母,用这个字母填充完全。
如果一个蛋糕上有两个或两个以上字母,可以切分为两块更小的蛋糕。两块小蛋糕至少有一个字母。

为使两块小蛋糕至少有一个字母,遵循的切割规则:

1. 如果字母全部都在一列上,从中间切开。(这种情况再竖着切只会得到全是?的一块)

??A
???
??C

得到

??A

???
??C

2. 选择最左的字母所在列的右边切开

?A?
B??
??C

得到

?
B
?

A?
??
?C

int r = Integer.parseInt(aline.split(" ")[0]);
int c = Integer.parseInt(aline.split(" ")[1]);
char[][] cake = new char[r][c];
for(int i=0;i<r;i++) {aline=reader.readLine();for(int j=0;j<c;j++) {cake[i][j] = aline.charAt(j);}
}
divide_and_conquer(cake,0,0,r,c);
private static void divide_and_conquer(char[][] cake,int si,int sj,int rno,int cno) {//si和sj是矩形的左上点的索引,rno是行数(宽度),cno是列数(长度)//(si,sj)      ... (si,sj+cno-1)//(si+rno-1,sj)... (si+rno-1,sj+cno-1)if(rno==1 && cno==1) return;//如果只有一个字符,用这个字符填充区域int lno = 0;char l = '?';for(int j=sj;j<=sj+cno-1;j++) {for(int i=si;i<=si+rno-1;i++) {if(cake[i][j]!='?') {lno++;l=cake[i][j];}}}if(lno==1) {for(int i=si;i<=si+rno-1;i++) {for(int j=sj;j<=sj+cno-1;j++) {cake[i][j]=l;}}return;}//如果全部字母存在一列上,从上到下找到第一个字母,从下到上找到最后一个字母,从两者中间切割,为保证切成的两块至少含有一个字母int llno = 0;  //记录字母是否都在一列上int llrno = 0;  //如果都在一列上,记录是都在哪一列上for(int j=sj;j<=sj+cno-1;j++) {for(int i=si;i<=si+rno-1;i++) {if(cake[i][j]!='?') {llno++;llrno=j;break;}}}if(llno==1) {int topj = si;int bottomj = si+rno-1;while(cake[topj][llrno]=='?')topj++;while(cake[bottomj][llrno]=='?')bottomj--;int medium = topj+(bottomj-topj)/2;divide_and_conquer(cake,si,sj,medium-si+1,cno);divide_and_conquer(cake,medium+1,sj,si+rno-1-medium,cno);return;}//找到最左的字母存在的列,从右边分割 for(int j=sj;j<=sj+cno-1;j++) {for(int i=si;i<=si+rno-1;i++) {if(cake[i][j]!='?') {divide_and_conquer(cake,si,sj,rno,j-sj+1);divide_and_conquer(cake,si,j+1,rno,cno-(j-sj+1));return;}}}
}

这篇关于Codejam之Alphabet Cake的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/718587

相关文章

CF629D Babaei and Birthday Cake

题意:给出N个半径,和高的圆柱,要求后面的体积比前面大的可以堆在前一个的上面,求最大的体积和。 dp[i]=max(dp[j])+v[i](j<i&&v[i]>v[j]); 离散化,线段树维护区间最大值 import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import

经典题hdu 1722 Cake

Cake Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2648 Accepted Submission(s): 1275  Problem Description 一次生日Party可能有p人或者q人参加,现准备有一个大蛋糕.问最少要

【递归+二叉树思想+搜索】 Alice and the Cake题解

Alice and the Cake题解 AC记录:记录-洛谷 题面翻译(大概就是题目大意) 执行恰好 n − 1 n-1 n−1 次操作,每次操作可以选择当前所有蛋糕中满足其重量 w ⩾ 2 w\geqslant 2 w⩾2 的一块,然后将其分为质量分别为 ⌊ w 2 ⌋ \lfloor\dfrac w2\rfloor ⌊2w​⌋ 和 ⌈ w 2 ⌉ \lceil\dfrac

hdu-2134-Cuts the cake

#include<stdio.h> #include<math.h> #define m 3.14 int main() {  int n;  double x,y=0;  while(scanf("%d",&n)&&n!=0)  {   x=sqrt(m*n*n/(3*m));   y=sqrt(2*m*x*x/m);   printf("%.3lf

POJ - 1020 Anniversary Cake

题意:有一块边长为BoxSize的正方形的大蛋糕,现在给出n块不同尺寸的正方形的小蛋糕的边长,问是否能把大蛋糕按恰好切割为这n块小蛋糕,要求每块小蛋糕必须为整块。 思路:有技巧性的DFS,这里有一篇写的很好的:点击打开链接 #include <iostream>#include <cstdio>#include <algorithm>#include <cstring>using

【HDU 5448】Marisa’s Cake

题意:给你一个包含n个点的凸包,所有可能出现凸包的面积和。 分析:首先比较暴力的方法就是n^2枚举一条边,求它对答案的贡献。但是点的个数有10^5,因此我们考虑从某一个点出发的所有有向面积。 若我们当前考虑的是第i个点,那么它与第i+1个点形成的这条边所能产生的凸包个数为(2^(n - 2) - 1)个,与第i + 2个点形成的这条边的个数为(2 ^ (n - 3) - 1)个……又因为叉积满

hdu 4454 Stealing a Cake(三分)

题目链接:hdu 4454 Stealing a Cake 题目大意:给定一个起始点s,一个圆形,一个矩形。现在从起点开始,移动到圆形再移动到矩形,求最短距离。 解题思路:在圆周上三分即可。即对角度[0,2*pi]三分,计算点和矩形的距离可以选点和矩形四条边的距离最短值。 #include <cstdio>#include <cstring>#include <cmath>#in

hdu 5448 Marisa’s Cake(几何+凸包)

题目链接:hdu 5448 Marisa’s Cake 解题思路 这题和zoj 3871 Convex Hull有点像,不过点数比较大,不能接受 o(n2) o(n^2)的算法。但是题目给定的是一个凸包,所以可以通过化简,在 o(n) o(n)的复杂度内计算出答案。 首先,对于一个三角形ABC SABC=fA×fB+fB×fC+fC×fA(fi表示点i和原点组成的向量) S_{

zoj 3905 Cake(状压dp)

题目链接:zoj 3905 Cake 代码 #include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 805;struct State {int a, b;State (int a = 0, int b = 0): a(a), b(b) {}bool operat

Codejam Round 1A 2020 Pattern Matching(构造)

Problem Many terminals use asterisks () to signify “any string”, including the empty string. For example, when listing files matching BASH, a terminal may list BASH, BASHER and BASHFUL. For FUL, it ma