每日算法 - day 16
每日算法
those times when you get up early and you work hard; those times when you stay up late and you work hard; those times when don’t feel like working — you’re too tired, you don’t want to push yourself — but you do it anyway. That is actually the dream. That’s the dream. It’s not the destination, it’s the journey. And if you guys can understand that, what you’ll see happen is that you won’t accomplish your dreams, your dreams won’t come true, something greater will. mamba out
那些你早出晚归付出的刻苦努力,你不想训练,当你觉的太累了但还是要咬牙坚持的时候,那就是在追逐梦想,不要在意终点有什么,要享受路途的过程,或许你不能成就梦想,但一定会有更伟大的事情随之而来。 mamba out~
2020.2.28
luogu-P1036 选数
思路: 素数筛选 + dfs 组合型枚举
有个很重要的一点就是确保你的dfs在传参数的时候保证意义和定义的函数是一致的
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
const int N = 25;
int n , k , a[N];
bool isprime(int x)
{
for(int i = 2;i <=sqrt(x) ; i++)
{
if(x % i == 0)return false;
}
return true;
}
int ans = 0;
void dfs(int cur,int sum,int index)
{
if(cur == k)
{
if(isprime(sum))ans++;
}else{
for(int i = index + 1 ;i < n ;i ++)
{
dfs(cur + 1,sum + a[i],i);
}
}
}
int main()
{
cin>> n >> k;
for(int i = 0;i < n ;i ++)cin >> a[i];
for(int i = 0;i < n - k + 1; i++)
{
dfs(1,a[i],i);
}
cout << ans << endl;
return 0;
}
luogu-P1086 花生采摘
这道题最坑得地方不是题难而是要好好读题!
借用大佬总结得坑 我几乎全部跳进去 还陶醉在里面优化了半天
其实一开始就感觉时间复杂度不太对劲,但是没往那方面想。 tcl
问题一:读题时应该仔细读。有的同学没有看到每次只能拿剩下花生株中最大的,而是希望找到一种在规定时间内能够拿最多花生的组合,把题目变成了另外一道题。
问题二:有的同学没有读到“没有两株花生株的花生数目相同”的条件,因此把题目复杂化了。
问题三:这个题目是假设猴子在取花生的过程中不会回到大路上的,有些同学在思考是否可能在中间回到大路上,因为题目没说在大路上移动要花时间,所以有可能中途出来再进去摘的花生更多。
重新梳理思路得就是贪心得思想我们只需要记录下来有花生得坐标和数量
对他们进行从大到小排序迭代判断规定时间内能完成得采摘个数即可
有个小地方是记录得时候从下标1开始留下 0 作为初始化进行迭代计算
认真读题!!!
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1001;
int n , m , k = 1;
int t, u , ans;
struct node{
int x, y , time,w;
};
node p[100001];
int a[N][N];
bool cmp(node a,node b)
{
return a.w > b.w;
}
int main()
{
cin >> m >> n >> t;
for(int i = 1;i <= m ;i ++)
{
for(int j = 1;j <= n ;j ++)
{
cin >> a[i][j];
if(a[i][j])
{
p[k].w = a[i][j];
p[k].x = i;
p[k].y = j;k++;
}
}
}
sort(p + 1, p + k ,cmp);
for(int i = 1;i <= k; i++)
{
u = p[i].x;
if(i == 1)p[i].time = p[i].x + 1;第一个花生是不同的,因为多多一开始可以跳到第一个最多花生的所在列。
else{
p[i].time = p[i-1].time + abs(p[i].x - p[i-1].x) +
abs(p[i].y - p[i-1].y) + 1;//不是第一个的话就加上与前一个的坐标差再加采摘时间。
}
if(p[i].time + u <= t)ans += p[i].w;//如果数据合法那么就把花生数加上。
}
cout << ans << endl;
return 0;
}
luogu-P1176 路径计数2
就是模板题 没啥做的 特判一下就OK
模板:
f[i][j] = f[i-1][j] + f[i][j-1]
初始化:f[1][0] = 1
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
const int N = 1010;
int f[N][N] , n , m ,x ,y;
bool cant[N][N];
int main()
{
cin >> n >> m;
for(int i = 0;i < m ;i ++)
{
scanf("%d %d",&x,&y);
cant[x][y] = 1;
}
f[1][0] = 1;
for(int i = 1;i <= n ;i ++)
{
for(int j = 1;j <= n ;j ++)
{
if(!cant[i-1][j])f[i][j] = (f[i][j] + f[i-1][j]) % 100003;
if(!cant[i][j-1])f[i][j] = (f[i][j] + f[i][j-1]) % 100003;
}
}
cout << f[n][n];
return 0;
}
luogu-P1087 FBI树
建树 --> 后序遍历 完事
好久没写树 差点忘记怎么写了 hhh 不过还好快速反应过来 快速AC hh
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <cmath>
using namespace std;
int n;
string s;
struct node{
string s;
node *left, * right;
};
char check(string s)
{
bool f1 = 0, f2 = 0;
for(int i = 0;i < s.size() ; i++)
{
if(s[i] == '1')f1 = 1;
if(s[i] == '0')f2 = 1;
}
if(f1 && f2)return 'F';
if(f1 && !f2)return 'I';
if(!f1 && f2)return 'B';
}
void build(string s,node *tree)
{
tree->s = s;
int len = s.size();
if(len == 1)return;
tree->left = new node();
tree->right = new node();
build(s.substr(0,len / 2),tree->left);
build(s.substr(len / 2,len / 2),tree->right);
}
void postorder(node *root)
{
if(root == NULL)return;
else{
postorder(root->left);
postorder(root->right);
cout << check(root->s);
}
}
int main()
{
cin >> n >> s;
node *tree = new node();
build(s,tree);
postorder(tree);
return 0;
}