只会打暴力,能混一点分是一点。
记录一下我的暴力写法。
I 李白打酒加强版
/*
样例输入
5 10
样例输出
14
*/
//dfs暴搜 能过40%
//看清题目限制条件,第一次写没注意 最后一次是遇到花
//第二次写 又没注意 遇到花的次数 和 遇到店的次数 ,没注意n,m的含义
//审题很关键,不然要浪费很多时间
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 25, mod = 1000000007;
typedef long long ll;
ll ans;
int path[N]; //记录路径
int n,m;
//参数u:第几次
//参数st:只有0或1,0表示遇到花,1表示遇到店
//参数t:表示遇到店或花之后的酒有几斗
void dfs(int u,int st,int t)
{
//出口
if(u==n+m)
{
if(t==0 && st==0)
{
int nn=0,mm=0;
//统计路径path中遇到花和店的次数
for(int i=1;i<=n+m;i++)
{
if(path[i]==0) mm++;
else nn++;
}
if(nn==n && mm==m)
{
ans++;
// for(int i=1;i<=n+m;i++) cout << path[i];
// puts("");
}
}
return;
}
//没酒只能遇到店
if(t==0) {
path[u+1] = 1;
dfs(u+1,1,t*2);
}
else{
path[u+1] = 1;
dfs(u+1,1,t*2);
path[u+1] = 0;
dfs(u+1,0,t-1);
}
}
int main()
{
cin >> n >> m;
path[1] = 0;
dfs(1,0,1); //遇到花,酒减1
path[1] = 1;
dfs(1,1,4); //遇到店,酒翻倍
cout << ans%mod << endl;
return 0;
}
J 砍竹子
/*
样例输入:
6
2 1 4 2 6 7
样例输出:
5
*/
//暴力写法,能过 20%
//递归思想:自己调用自己
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
ll a[N];
int st[N];//存状态 记得每次遍历要更新状态
ll ans;
int n;
//判断是否到最后的状态,即a[i]是否全为1
bool is_end()
{
int flag = 0;
for(int i=1;i<=n;i++)
if(a[i] != 1) flag = 1;
if(!flag) return true;
else return false;
}
//找连通块
void dfs(int u)
{
st[u] = 1;
//左右两个方向的方向向量
int d[] = {-1,1};
for(int i=0;i<2;i++)
{
int x = u+d[i];
//条件限制考虑要严谨,不然容易越界和死循环
if(a[x]==a[u] && x>=1 && x<=n && !st[x])
{
st[x] = 1;
dfs(x);
}
}
}
void dfs_main()
{
ans ++;
ll mmax = 0;
int idx;
//找最大值
for(int i=1;i<=n;i++)
{
if(a[i] > mmax)
{
mmax = a[i];
idx = i;
}
}
//状态更新
memset(st, 0, sizeof st);
//找连通块
dfs(idx);
for(int i=1;i<=n;i++)
{
//floor(x) 下取整函数
if(st[i]==1) a[i] = floor(sqrt(a[i]/2 + 1));
// cout << a[i] << ' ';
}
// puts("");
// for(int i=1;i<=n;i++) cout << st[i] << ' ';
if(!is_end()) dfs_main();
}
int main()
{
cin >> n;
for(int i=1;i<=n;i++) cin >> a[i];
dfs_main();
cout << ans << endl;
return 0;
}