【解题报告】 SRM412_div1_250pt 和 SRM411_div2_900pt
来源:互联网 发布:切削参数计算软件 编辑:程序博客网 时间:2024/05/21 16:11
SRM412_div1_250: Forbidden String
题目链接请点击这里。
题目描述:只考虑由A,B,C三字母组成的字符串,若字符串S存在三个连续的字母使得其中一个为A,一个为B,一个为C,则称S为forbidden string。例如,BAACAACCBAAA 是Forbidden String,而AABBCCAABB 不是。
给你字符串长度n,要求你计算有多少个not forbidden字符串。1<=n<=30。
解析1:可模拟字符串从长度为0开始不断往后append字母至长度为n的过程。当前位可添加的字母仅由其前2位决定(如果长度>=2的话,若长度<2可自由添加),而其前2位可能的情况有以下几种:AA,BB,CC,AB,AC,BC,BA,CA,CB
分别用1,2,3表示A,B,C的话,则可以用不大于40的几个数来表示所有可能的前缀。另外n的范围较小,因此首先想到用dp解决。dp[a][b]表示前a位的末2位对应整数为b时的非forbidden string数量(b=11,22,33,12,13,23,21,31,32)。则根据b的情况进行讨论,进行状态转换。当b对应的前缀其2位均相同时,则可添加A,B,C三种。当b对应的前缀其2位不同时,则可添加2种,具体哪2种由b决定。例如b=BA时,可添加A,B两种,不能添加C。
解析2:在解析1的基础上,我们知道最终not forbidden的字符串只由两类字符串组成:末2位相同和末2位不同的字符串,用r[t]表示长度为t且末2位相同的非forbidden字符串。用n[t]表示末2位不相同的非forbidden字符串。则r[t], n[t]与r[t-1], n[t-1]之间存在什么样的关系?由解析1可很容易地推出:
r[t] = r[t-1]+n[t-1];
n[t]=r[t-1]*2+n[t-1];
由此可在O(n)时间内解决。
typedef long long ll;
long long ForbiddenStrings::countNotForbidden(int N) {
if(N == 1) return 3;
if(N == 2) return 9;
ll r[100], n[100];//r:the forbidden string that the last 2 chars are same. n:the forbidden string that the last 2 are diff.
r[2]=3;n[2]=6;
for(int i = 3; i <= N; i++){
r[i] = r[i-1]+n[i-1];
n[i] = n[i-1]+r[i-1]*2;
}
return r[N]+n[N];
}
SRM411_div2_900: HoleCakeCuts
题目链接请点击这里。
题目描述:有一个正方形蛋糕,其中心点坐标为(0,0),X轴正向向右,Y轴正向向上,均与正方形边长平行。蛋糕边长为2O。在其内挖走一块边长为2I的同心正方形(即中心点也在(0,0))。然后对这个特殊的蛋糕进行横向(与Y轴平行)或纵向(与X轴平行)的切割。切割坐标已知(即横向切割的Y坐标和纵向切割的X坐标)。每个切割的长度均是无限的。求切割之后还剩多少块蛋糕(面积>0)。
题目解析:先不管蛋糕内的空心洞。用(x1,y1,x2,y2)表示一块矩形区域,其中x1,y1为左上角坐标,x2,y2为右下角坐标。每次切割都将当前矩形分为两部分,横向切割分为上下,纵向切割分为左右,根据切割坐标可得到两部分的左上角和右下角的坐标,由此进行递归。
关键问题在于,由于存在空心洞,因此需要注意两种情况:
即当某个切使得其得到的子矩形中有被空洞一分为二的情况时,此时这个子矩形不是一个完整的矩形(只剩下头和尾两部分,见图中黄色区域,中间都是空的),此时必须分将此子矩形为上下或左右两个子部分(中间的为空不包括在内),然后继续切割。根据空洞的边长可得到其左右或上下两个子块的坐标。代码如下:
class HoleCakeCuts {
public:
int cutTheCake(int, int, vector <int>, vector <int>);
};
int out,in;
vector<pair<int,char> > cut;
bool In(int x1,int y1,int x2,int y2){
if(abs(x1)<=in && abs(x2)<=in && abs(y1)<=in && abs(y2)<=in) return true;
return false;
}
int solve(int x1,int y1,int x2,int y2,int p1){
if(In(x1,y1,x2,y2)) return 0;//if current area is totally included by In, that means this area is empty.
if(x1==x2 || y1==y2) return 0;//area should >0
if(p1 == cut.size()){
if(x1>=-in && x2<=in && y1>=in && y2<=-in) return 2;//key point! If current area is seprated by In into 2 parts.
if(y1<=in && y2>=-in && x1<=-in && x2>=in) return 2;//key point! Then this area should count as 2 areas.
return 1;
}
if(x1>=-in && x2<=in && y1>=in && y2<=-in){//key point! If area is sperated by In into 2parts.
return solve(x1,y1,x2,in,p1)+solve(x1,-in,x2,y2,p1);
}
else if(y1<=in && y2>=-in && x1<=-in && x2>=in){//Then we should seperate it into 2parts, ans handle individually.
return solve(x1,y1,-in,y2,p1)+solve(in,y1,x2,y2,p1);
}
bool ish=false,isv=false;
int i;
for(i = p1; i < cut.size(); i++){
if(cut[i].second == 'h'){
if(cut[i].first <= y1 && cut[i].first >=y2){//valid cut for current area.
ish = true;
break;
}
}
else{
if(cut[i].first >= x1 && cut[i].first <=x2){//valid cut for current area.
isv = true;
break;
}
}
}
if(!ish && !isv) return solve(x1,y1,x2,y2,p1+1);//this cut is invalid for current area. Then just move on.
if(ish){//horizonal cut
return solve(x1,y1,x2,cut[i].first,p1+1)+solve(x1,cut[i].first,x2,y2,p1+1);
}
else{//vertical cut
return solve(x1,y1,cut[i].first,y2,p1+1)+solve(cut[i].first,y1,x2,y2,p1+1);
}
}
int HoleCakeCuts::cutTheCake(int cakeLength, int holeLength, vector <int> h, vector <int> v) {
out=cakeLength;
in=holeLength;
cut.clear();
for(int i = 0; i < h.size(); i++)
cut.push_back(make_pair(h[i],'h'));
for(int i = 0; i < v.size(); i++)
cut.push_back(make_pair(v[i],'v'));
return solve(-out,out,out,-out,0);//topleftx,toplefty,downrightx,downrighty
}
- 【解题报告】 SRM412_div1_250pt 和 SRM411_div2_900pt
- 翔特卡洛和解题报告
- 序列和解题报告
- NYOJ16和NYOJ17解题报告
- 最小和[CODEVS1635]解题报告
- 子集和问题 解题报告
- POJ 2739(连续素数和) 解题报告
- 【最大子序列和】解题报告
- 【字符串】漏洞和补丁解题报告
- 蓝桥杯练习题-《道路和航路》解题报告
- 习题1-3 连续和 解题报告
- (解题报告)HDU2007---平方和与立方和
- 剑指offer和leetcode解题报告
- 洛谷最大子树和解题报告
- cogs2790. mk和tree解题报告
- 解题报告
- 解题报告
- 解题报告
- JS控制页面安全,复制、保存、邮件、打印。
- Log调试
- java基础4--面向对象(下)(抽象类与接口)
- 为apt-get设置HTTP代理(使用代理更新Ubuntu的方法)
- oracle 闪回关于触发器的bug
- 【解题报告】 SRM412_div1_250pt 和 SRM411_div2_900pt
- 第一天
- sssssssssss
- Iphone开发(1)
- 快速排序算法
- windows Socket I/O模型简单说明
- zju1086 (高精度)解题报告
- 使用ant进行android开源voip工程sipdroid的编译与apk生成
- 快递公司春节休假表新鲜出炉