目录
1.游游的you
2.腐烂的苹果
3.孩子们的游戏
1.游游的you
链接:
分析题意之后,发现就是一道简单的贪心,当然也可以把他看作纯数学题。
因为you和oo里面都有o,但是you可以得两分,所以贪心策略尽可能的去凑更多的you,剩下的o则是n - 1分。
详细代码:
#include <iostream>
using namespace std;
int x,y,z;
int main() {
int n;
cin >> n;
while(n--)
{
cin >> x >> y >> z;
int mi = min(x,min(y,z));
y -= mi;
if(y > 0)
cout << mi * 2 + y - 1 << endl;
else
cout << mi * 2 << endl;
}
}
注意:
要判断剩下的y是否大于0,不然会导致部分样例出错。
2.腐烂的苹果
链接
我一开始分析这道题目的时候,想到的竟然是DFS遍历,压根做不出来,因为做不到多源搜索。
正解应该是BFS的多源搜索。
首先先遍历grid,将所有的腐烂苹果存入队列,进行多源搜索。
最后需要返回的时候应该判断有没有苹果1没被感染到。
详细代码:
class Solution {
public:
const static int N = 1010;
int dx[4] = { 0, 0, 1, -1 };
int dy[4] = { 1, -1, 0, 0 };
bool vis[N][N] = { false };
int m, n;
int time = 0;
queue<pair<int, int>> q;
void BFS(vector<vector<int> >& grid) {
while (q.size()) {
time++;
int size = q.size();
while (size--) {
int x = q.front().first;
int y = q.front().second;
q.pop();
for (int i = 0; i < 4; ++i) {
int a = x + dx[i];
int b = y + dy[i];
if (a >= 0 && a < m && b >= 0 && b < n
&& grid[a][b] == 1 && !vis[a][b]) {
vis[a][b] = true;
q.push({ a, b });
}
}
}
}
}
int rotApple(vector<vector<int> >& grid) {
m = grid.size();
n = grid[0].size();
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == 2) {
q.push({ i, j });
}
}
}
// BFS遍历
BFS(grid);
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == 1 && !vis[i][j])
return -1;
}
}
return time - 1;//最后的苹果还会进行一次无效遍历 减掉那次
}
};
怎么说呢,算是一道比较难的题目吧,个人觉得。
3.孩子们的游戏
链接
就是约瑟夫的环形链表。
方法一:模拟
可以用环形链表或者数组来模拟实现:
(这里我写的是环形链表)
class Solution {
public:
typedef struct ListNode ListNode;
ListNode* ListBuyNode(int x) {
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
if (node == NULL) {
perror("malloc fail!");
exit(1);
}
node->val = x;
node->next = NULL;
return node;
}
//创建带环链表
ListNode* CreateList(int n) {
ListNode* phead = ListBuyNode(1);
ListNode* ptail = phead;
for (int i = 2; i <= n; i++) {
ListNode* node = ListBuyNode(i);
ptail->next = node;
ptail = ptail->next;
}
ptail->next = phead;
return ptail;
}
//n = 5;m = 2;
int LastRemaining_Solution(int n, int m) {
ListNode* prev = CreateList(n);
ListNode* cur = prev->next;
int count = 1;
while (cur->next != cur) {
if (count == m) {
//杀掉
prev->next = cur->next;
free(cur);
cur = prev->next;
count = 1;
}
else {
prev = cur;
cur = cur->next;
count++;
}
}
return cur->val - 1;
}
};
减一是因为我写的是从1开始的,而题目是从0开始。
方法二:递推/ 动态规划
就是只需要寻找 dp[n] 和 dp[n - 1] 的映射关系就好了。
图中所画的内环是i - 1,外环是i。分析很容易得到dp[i]与dp[i - 1]的关系为dp[i] = dp[i - 1] + m。
最后为了防止+m后超出n,因此模上一个n(目前的数量)。
因此:
class Solution
{
public:
int dp[5010];
int LastRemaining_Solution(int n, int m)
{
dp[1] = 0;
for (int i = 2; i <= n; i++)
dp[i] = (dp[i - 1] + m) % i;
return dp[n];
}
};
因为只有一维,而且状态转移方程只涉及一个数,也可以不创建dp表,用一个变量来表示。
class Solution
{
public:
int LastRemaining_Solution(int n, int m)
{
int f = 0;
for (int i = 2; i <= n; i++) f = (f + m) % i;
return f;
}
};