蓝桥杯-枚举模板题
- 滑雪课程设计 P3650
- 新的家乡 P8587
- 枚举子集 B3622
- Air Cownditioning P9011
滑雪课程设计 P3650
核心的思路是把数据规定在[i,i+17]里,不够的补,过大的减。枚举i以求最少的钱。
#include<bits/stdc++.h>
using namespace std;
int n;
int a[1010];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
int ans = 1e9;
for (int low = 1; low <= 100; low++)
{
int high = low + 17;
int sum = 0;
for (int i = 0; i < n; i++)
{
if (a[i] < low) sum += (low - a[i]) * (low - a[i]);
if (a[i] > high) sum += (a[i] - high) * (a[i] - high);
}
ans = min(ans, sum);
}
cout << ans;
return 0;
}
新的家乡 P8587
核心思路是去枚举和。
[1,x-1];[2,x-2]~[x/2(下取整),x/2(上取整)]找两个元素的较少的那个。
特判比如3 3 3 3 3找6,此次不满足上一条,见代码特判处。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int a[N], cnt[N];
signed main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)cin >> a[i];
for (int i = 0; i < n; i++)cnt[a[i]]++;
int ans1 = 0;
int ans2 = 0;
for (int x = 2; x <= 6000; x++)
{
int sum = 0;
for (int i = 1; i <= x / 2; i++)//枚举小的一半
{
if (i * 2 == x)//这个是特判,一般走else
{
sum += cnt[i] / 2;
}
else
{
sum += min(cnt[i], cnt[x - i]);
}
}
if (sum > ans1) ans1 = sum, ans2 = 1;
else if (sum == ans1) ans2++;
}
cout << ans1 << ' ' << ans2;
return 0;
}
枚举子集 B3622
核心思路是用位运算来模拟选与不选。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int n;
signed main()
{
cin >> n;
for (int i = 0; i < (1 << n); i++)
{
for (int j = n - 1; j >= 0; j--)//从大到小枚举
{
if ((i >> j) & 1)
{
cout << 'Y';
}
else
cout << 'N';
}
cout << endl;
}
return 0;
}
Air Cownditioning P9011
核心思路依然是用位运算枚举空调状态,但过程与数据更加复杂。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 110;
int a[N], b[N], p[N], cost[N], s[N], t[N], c[N];
int f[N], need[N];
signed main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> s[i] >> t[i] >> c[i];
for (int j = s[i]; j <= t[i]; j++)
{
need[j] = max(c[i], need[j]);//更新要求
}
}
for (int i = 1; i <= m; i++)cin >> a[i] >> b[i] >> p[i] >> cost[i];//以上为读入数据
int ans = 0x3f3f3f3f;
for (int state = 0; state < (1 << m); state++)//枚举空调用或不用
{
memset(f, 0, sizeof f);
for (int j = 0; j < m; j++)
{
if ((state >> j) & 1)//第j台用不用
{
for (int x = a[j + 1]; x <= b[j + 1]; x++)
{
f[x] += p[j + 1];
}
}
}
bool flag = true;
for (int i = 1; i <= 100; i++)
{
if (f[i] < need[i])//比如需要降低2度,结果就降了1度,那肯定不对了
{
flag = false;
}
}
if (flag)
{
int sum = 0;
for (int j = 0; j < m; j++)
{
if ((state >> j) & 1)
{
sum += cost[j + 1];
}
}
ans = min(ans, sum);
}
}
cout << ans;
return 0;
}