1. 551. Student Attendance Record I

2. 552. Student Attendance Record II

hihocode原题,https://hihocoder.com/contest/offers10/problems

直接粘贴代码。

其实这个第二题的问题挺多的,这里还是写一下分析过程。

我刚开始做的时候,考虑也是计数dp,一维记录a的个数,一维记录末尾l的个数,然后考虑转移,后来好像是因为转移情况复杂,简化为不考虑a的个数,因为a的个数只有1个,所以可以单独考虑,然后考虑只有p和l的情况,这样的问题应该是很好考虑的,我写的有点

复杂,我是记录末尾是什么,其实只用考虑末尾l的个数就行,只用一维就可以解决,而我使用了2维,枚举最后的2个字符是什么,还是比较繁琐的。计算过程,就是状态的转移过程,很好理解。

接下来考虑a的情况,最后的结果肯定先要加上没有a的情况,然后枚举a的位置,然后左右2边就又变成上面没a的情况,把左和右乘起来,就是最后的结果。

我的做法不具有通用性,而且绕的弯子有点大,没有抓住问题的本质。

接下来考虑正常的做法,计数dp,一维记录a的个数,一维记录末尾l的个数,然后考虑转移的情况。

转移的详细分析:http://bookshadow.com/weblog/2017/04/16/leetcode-student-attendance-record-ii/

其实自己手动分析,其实也是很简单的。

注意:上面的考虑的是,谁可以转移到我,这是一个收集的过程,分析可能的情况,而且情况数目很多,代码量大,很容易出错

解法二:

 #include<bits/stdc++.h>
#define pb push_back
typedef long long ll;
using namespace std;
typedef pair<int, int> pii;
const int maxn = 1e5 + ;
const int mod = 1e9 + ;
ll dp[maxn][][];
int n;
void add(ll& x, ll y) {
x = (x + y) % mod;
}
void solve() {
cin >> n;
dp[][][] = ;
for (int i = ; i <= n; i++) {
add(dp[i][][], dp[i - ][][]);
add(dp[i][][], dp[i - ][][]);
add(dp[i][][], dp[i - ][][]); add(dp[i][][], dp[i - ][][]);
add(dp[i][][], dp[i - ][][]); add(dp[i][][], dp[i - ][][]);
add(dp[i][][], dp[i - ][][]); add(dp[i][][], dp[i - ][][]);
add(dp[i][][], dp[i - ][][]);
add(dp[i][][], dp[i - ][][]);
add(dp[i][][], dp[i - ][][]);
add(dp[i][][], dp[i - ][][]);
add(dp[i][][], dp[i - ][][]); }
ll res = ;
for (int i = ; i < ; i++)
for (int j = ; j < ; j++)
add(res, dp[n][i][j]);
cout << res << endl;
} int main() {
freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
ios::sync_with_stdio();
cin.tie(); cout.tie();
solve();
return ;
}

转移复杂,需要考虑的情况多。

然后我参考排行榜第一名的代码,就有下面的分析:

所以就有下面的分析:其实应该考虑的是:我可以转移到谁,这是一个分发的过程,因为当前字符可能为a,p, l,所以是很好考虑的,代码也相对好写些

解法三:

 #include<bits/stdc++.h>
#define pb push_back
typedef long long ll;
using namespace std;
typedef pair<int, int> pii;
const int maxn = 1e5 + ;
const int mod = 1e9 + ;
ll dp[maxn][][];
int n;
void add(ll& x, ll y) {
x = (x + y) % mod;
}
void solve() {
cin >> n;
dp[][][] = ;
for (int i = ; i < n; i++) {
for (int x = ; x < ; x++) {
for (int y = ; y < ; y++) {
ll cur = dp[i][x][y];
if(cur == ) continue;
add(dp[i + ][x][], cur);
if(x + < ) {
add(dp[i + ][x + ][], cur);
}
if(y + < )
add(dp[i + ][x][y + ], cur);
}
}
}
ll res = ;
for (int i = ; i < ; i++)
for (int j = ; j < ; j++)
add(res, dp[n][i][j]);
cout << res << endl;
} int main() {
freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
ios::sync_with_stdio();
cin.tie(); cout.tie();
solve();
return ;
}

上面的代码都可以采用滚动数组优化。

其实分析到这里就差不多了,更详细的做法是贴出代码,一步一步解释,但是那样实在是太麻烦了,许多事情还是需要自己去走一遍的。

上面算是3种方法,第三种是最好的。

这个题目的n的限制为1e5,其实如果为1e8, 可以做么,其实是可以的,搞出来一个转移矩阵,然后快速幂来解决的,这也算是通用的套路吧。

转移矩阵的写法:

 #include<bits/stdc++.h>
#define pb push_back
typedef long long ll;
using namespace std;
typedef pair<int, int> pii;
const int maxn = 1e3 + ;
const int mod = 1e9 + ;
struct mat {
ll a[][];
mat() {
memset(a, , sizeof a);
}
void pr() {
for (int i = ; i < ; i++) {
for (int j = ; j < ; j++)
cout << a[i][j] << " ";
cout << endl;
}
}
};
mat mul(mat& a, mat& b) {
mat c;
for (int i = ; i < ; i++) {
for (int j = ; j < ; j++) {
for (int k = ; k < ; k++) {
c.a[i][j] = (c.a[i][j] + a.a[i][k] * b.a[k][j] % mod) % mod;
}
}
}
return c;
}
mat tr, one;
int f(int x, int y) {
return x * + y;
}
void init() {
for (int i = ; i < ; i++) {
for (int j = ; j < ; j++) {
int cur = f(i, j);
one.a[cur][cur] = ;
tr.a[cur][f(i, )] = ;
if(i + < )
tr.a[cur][f(i + , )] = ;
if(j + < )
tr.a[cur][f(i, j + )] = ;
}
} }
int n;
void solve() {
cin >> n;
init();
//tr.pr();
//one.pr();
mat res;
res.a[][] = ;
while(n) {
if(n & ) one = mul(one, tr);
n >>= ;
tr = mul(tr, tr);
}
res = mul(res, one);
ll r = ;
for (int i = ; i < ; i++)
r = (r + res.a[][i]) % mod;
cout << r << endl;
} int main() {
freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
ios::sync_with_stdio();
cin.tie(); cout.tie();
solve();
return ;
}

相关的题目:

https://hihocoder.com/contest/offers13/problem/4  需要搞出状态转移方程,然后快速幂解决。

https://codejam.withgoogle.com/codejam/contest/10214486/dashboard#s=p3 这个难度比较高,也是转移方程的构造。

就这样吧,写了这么多啰嗦的话,本来只是想贴一下自己写的。

同时也暴露出一个问题,题目不是自己ac就完了,需要看一下别人是怎么做的,怎么想的,有没有什么巧妙的思路,这个过程才是关键的,这样才能提高和进步。

 class Solution {
public:
bool checkRecord(string s) {
int n = s.size();
int a = ;
for (int i = ; i < n; i++) {
if(s[i] == 'A') {
a++;
if(a > ) return ;
}
if(s[i] == 'L') {
if(i + < n && s[i + ] == 'L' && s[i + ] == 'L')
return ;
}
}
return ;
}
};
 typedef long long ll;
const int maxn = 1e5 + ;
const int mod = 1e9 + ;
ll dp[maxn][][];
ll s[maxn];
class Solution {
public:
int checkRecord(int n) {
if(n == ) {
//cout << 3 << endl;
return ;
}
if(n == ) {
//cout << 8 << endl;
return ;
}
// O L A
// 0 1 2
memset(s, , sizeof s);
memset(dp, , sizeof dp);
for (int i = ; i < ; i++)
for (int j = ; j < ; j++)
dp[][i][j] = ;
for (int c = ; c <= n; c++) {
for (int i = ; i < ; i++) {
for (int j = ; j < ; j++) {
for (int x = ; x < ; x++) {
if(i == && j == && x == ) {
continue;
}
dp[c][j][x] = (dp[c][j][x] + dp[c - ][i][j]) % mod;
}
}
}
for (int i = ; i < ; i++) {
for (int j = ; j < ; j++) {
s[c] = (s[c] + dp[c][i][j]) % mod;
}
}
}
ll res = ;
res = s[n];
s[] = ;
s[] = ;
s[] = ;
for (int i = ; i <= n; i++) {
int left = i - , right = n - i;
res = (res + s[left] * s[right] % mod) % mod;
}
return res; }
};

3. 553. Optimal Division

刚开始,看到长度为10,以为是暴力枚举,因为枚举每一个位置的优先级,然后计算,但是仔细想想,要是实现起来还是比较麻烦的。考虑到是第二题,不会这么麻烦,考虑

数学的分析方法,结果最大,除数最小,什么时候最小,当然是连除,越除越小,然后答案就很明显了。直接输出结果。

 class Solution {
public:
string optimalDivision(vector<int>& nums) {
int n = nums.size();
stringstream ss;
if(n == ) {
ss << nums[];
} else if(n == ) {
ss << nums[] << "/" << nums[];
} else {
ss << nums[] << "/(" << nums[];
for (int i = ; i < n; i++)
ss << "/" << nums[i];
ss << ")";
}
return ss.str();
}
};

4. 555. Split Concatenated Strings

说实话,看完真的一点想法也没有,完全懵逼。

静下心来分析,考虑整个字符串长度为1000,那么可以简单的枚举每一个字符串的开始,每一个字符都有可能作为开头,接下来考虑,固定头部的时候,其他的字符串怎么办,其实是很明显的,因为其他字符串只有顺序和逆序2种情况,而且要使得结果最大,肯定选择2种里面较大的那一种,显然是确定的,所以枚举的每一个起始字符以后,可以在O(n)的复杂度内,计算出这个串,然后不断的更新结果,就可以了。

 class Solution {
public:
string splitLoopedString(vector<string>& v) {
int n = v.size();
if(n == ) return "";
string res;
for (string&t : v) {
string td = t;
reverse(td.begin(), td.end());
if(td > t)
t = td;
res += t;
}
//cout << res << endl;
for (int i = ; i < n; i++) {
int sz = v[i].size();
for (int j = ; j < sz; j++) {
string ml = v[i].substr(j, sz - j), mr = v[i].substr(, j);
string rl = v[i].substr(j + , sz - j - ), rr = v[i].substr(, j + );
reverse(rl.begin(), rl.end());
reverse(rr.begin(), rr.end());
// ml mr
// rr rl
for (int j = (i + ) % n; j != i; j = (j + ) % n) {
ml += v[j];
rr += v[j];
} ml += mr;
rr += rl;
//cout << ml << endl;
//cout << rr << endl;
res = max(res, max(ml, rr));
}
}
return res;
}
};

LeetCode Weekly Contest 28的更多相关文章

  1. LeetCode Weekly Contest 8

    LeetCode Weekly Contest 8 415. Add Strings User Accepted: 765 User Tried: 822 Total Accepted: 789 To ...

  2. leetcode weekly contest 43

    leetcode weekly contest 43 leetcode649. Dota2 Senate leetcode649.Dota2 Senate 思路: 模拟规则round by round ...

  3. LeetCode Weekly Contest 23

    LeetCode Weekly Contest 23 1. Reverse String II Given a string and an integer k, you need to reverse ...

  4. Leetcode Weekly Contest 86

    Weekly Contest 86 A:840. 矩阵中的幻方 3 x 3 的幻方是一个填充有从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等. 给定一个 ...

  5. LeetCode Weekly Contest

    链接:https://leetcode.com/contest/leetcode-weekly-contest-33/ A.Longest Harmonious Subsequence 思路:hash ...

  6. 【LeetCode Weekly Contest 26 Q4】Split Array with Equal Sum

    [题目链接]:https://leetcode.com/contest/leetcode-weekly-contest-26/problems/split-array-with-equal-sum/ ...

  7. 【LeetCode Weekly Contest 26 Q3】Friend Circles

    [题目链接]:https://leetcode.com/contest/leetcode-weekly-contest-26/problems/friend-circles/ [题意] 告诉你任意两个 ...

  8. 【LeetCode Weekly Contest 26 Q2】Longest Uncommon Subsequence II

    [题目链接]:https://leetcode.com/contest/leetcode-weekly-contest-26/problems/longest-uncommon-subsequence ...

  9. 【LeetCode Weekly Contest 26 Q1】Longest Uncommon Subsequence I

    [题目链接]:https://leetcode.com/contest/leetcode-weekly-contest-26/problems/longest-uncommon-subsequence ...

随机推荐

  1. @RequestMapping与controller方法返回值介绍

    @RequestMapping url映射:定义controller方法对应的url,进行处理器映射使用.@RequestMapping(value="/item")或@Reque ...

  2. Idea 创建maven web项目(手工创建)

    参考链接:https://www.cnblogs.com/justuntil/p/7511787.html 话不多说,直接上图: 1.创建maven项目 创建项目完成,项目结构如下: 2.项目部署配置 ...

  3. 【转】jmeter定时调度,持续并发,使用简介

    一.安装Jmeter 1.下载Jmeter 下载地址:http://jmeter.apache.org/download_jmeter.cgi 目前最新版为2.9,其余文件如源代码等也可从如下官网下载 ...

  4. python str操作

    1. str.format():使用“{}”占位符格式化字符串(占位符中的索引号形式和键值对形式可以混合使用). 1 >>> string = 'python{}, django{} ...

  5. Eclipse安装和使用TFS

    第一步下载Tfs插件 去微软官网下载https://www.microsoft.com/en-us/download/details.aspx?id=4240 点击 选择下载 随便放置到一个本地或者服 ...

  6. Linux内核同步:per_cpu变量

    per cpu变量相关函数和宏 DEFINE_PER_CPU_SHARED_ALIGNED(type,name):静态分配per_cpu数组,数组名为name,结构类型为type DEFINE_PER ...

  7. hdu 1584 蜘蛛纸牌

    把小的牌放到大的牌上,求最小移动的距离和 DFS遍历所有的可能,把每一张牌与之要移动的牌都进行两层for的循环,注意回溯条件满足立刻break 代码(算法借鉴) #include <bits/s ...

  8. linu学习第二天:文件系统相关操作

    1 ---第二天笔记--- 2 查看操作系统版本:cat /etc/redhat-release, /etc/os-release 3 命令:lsb_release 4 查看内存 和 swap分区:f ...

  9. 第四节:Web爬虫之pyquery解析库

    PyQuery库也是一个非常强大又灵活的网页解析库,如果你有前端开发经验的,都应该接触过jQuery,那么PyQuery就是你非常绝佳的选择,PyQuery 是 Python 仿照 jQuery 的严 ...

  10. 【codeforces 767A】Snacktower

    [题目链接]:http://codeforces.com/contest/767/problem/A [题意] 每天掉一个盘子下来;盘子有大小从1..n依次增大n个盘子; 然后让你叠盘子; 最底层为n ...