问题描述
评测用例规模与约定
输入格式
输出格式
样例输入
6
2 1 4 2 6 7
样例输出
5
观察题目,不难想到的第一种方法,即利用贪心策略,每次砍断竹子最大的且连续的队列,由于队列中会出现很多重复长度的竹子造成算法冗余,故我还加入了去重的操作,奈何时间还是超限... 但对于小数据样本是可以的
#include<iostream>
#include<math.h>
using namespace std;
int cut(long long bamboo[], int n);
int Maxbamboo(long long bamboo[], int n);
int compression(long long bamboo[], int n, int &m);
int main()
{
long long bamboo[200000];
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> bamboo[i];
cout << cut(bamboo, n) << endl;
return 0;
}
int cut(long long bamboo[], int n)
{
int count = 0;
int m, len;
//每次砍最高的竹子
while(m = Maxbamboo(bamboo, n),bamboo[m]!=1)
{
len = compression(bamboo, n, m);
long long key = bamboo[m];
long long data = sqrt(key / 2 + 1);
for (int i = m; i < len && bamboo[i] == key; i++)
bamboo[i] = data;
count++;
n = len;
}
return count;
}
int Maxbamboo(long long bamboo[], int n)
{
int max = 0;
for (int i = 0; i < n; i++)
if(bamboo[i] > bamboo[max])
max = i;
return max;
}
int compression(long long bamboo[], int n, int &m)
{
int pre = bamboo[0];
int len = 1;
for (int i = 1; i < n ; i++)
{
if(bamboo[i]!=pre)
{
if(i == m)
m = len;
bamboo[len++] = bamboo[i];
pre = bamboo[i];
}
}
return len;
}
由于时间超限,故我选择搜寻他法,找到了另一种灵活算法,它的基本思想就是利用代价,每次让每个相邻不同的竹子进行代价计算,遇到相同梯次时即可停止,因为后续它们会一起砍断。此处@b站up主,3258 砍竹子_哔哩哔哩_bilibili
#include<iostream>
#include<math.h>
using namespace std;
int cut(long long bamboo[], int n);
int main()
{
long long bamboo[200000];
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> bamboo[i];
cout << cut(bamboo, n) << endl;
return 0;
}
int cut(long long bamboo[], int n)
{
long long echelon[10000];
int len = 0,count = 0;
while(bamboo[0] > 1)
{
echelon[len++] = bamboo[0];count++;
bamboo[0] = sqrt(bamboo[0] / 2 + 1);
}
for (int i = 1; i < n; i++)
{
long long v = bamboo[i];
while(v > 1)
{
int flag = 0;
for (int j = 0; j < len; j++)
if(echelon[j]==v)
{ flag = 1;break; }
if(flag) break;
count++;
v = sqrt(v / 2 + 1);
}
len = 0;
while(bamboo[i]>1)
{
echelon[len++] = bamboo[i];
bamboo[i] = sqrt(bamboo[i] / 2 + 1);
}
}
return count;
}