ACM学习笔记DAY2
今天学习的主要内容为模拟与贪心
- 模拟
就是根据实际问题建立模型,模拟实际程序走一遍。(但是有些思维的难度较大)
例如:
#include<iostream>
#include<stdio.h>
#pragma warning(disable:4996)
#define ll long long
int main()
{
ll n;
while (~scanf("%lld", &n))
{
for (ll i = 2; i * i <= n; i++)
while (n % (i * i) == 0)
n /= i;
printf("%lld\n", n);
}
return 0;
}
- 贪心
贪心算法是指不从整体上最优解考虑,算法得到的是某种意义上的最优解。
这道题有两种方案,一种是让速度最快的人往返接送,最快的人来来往往送完全部的人过河,每次的往返为一个局部,时间为t1
第二种方案是最快的人与次快的人去对岸,最快的人回到此岸,最慢的人再和次慢的人去对岸,次快的人回到此案此岸,时间为t2
之后最优的解就是min(t1,t2)
#include<iostream>
#include<algorithm>
using namespace std;
int a[10000];
int main() {
int t;
cin >> t;
while (t--)
{
int sum = 0;
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
sort(a , a + n );
while (n > 3) {
int t1 = 2 * a[0] + a[n - 1] + a[n - 2];
int t2 = 2 * a[1] + a[0] + a[n - 1];
sum += min(t1, t2);
n -= 2;
}
if (n == 1 || n == 3) {
for (int i = 0; i < n; i++) sum += a[i];
}
else if (n == 2) sum += a[1];
cout << sum << endl;
}
}
接下来是今天在vj上遇到的没有ac的题
这道题当时写的时候一直超时,最后在考试结束后看了题解才ac
#include<iostream>
#include <algorithm>
#pragma warning(disable:4996)
using namespace std;
#define maxn 25005
struct Node {
int u, v;
} E[maxn];
bool cmp(Node a, Node b) {
return a.u < b.u;
}
int main() {
int N, T, flag, ans, right, i;
while (scanf("%d%d", &N, &T) == 2) {
for (i = 0; i < N; ++i)
scanf("%d%d", &E[i].u, &E[i].v);
sort(E, E + N, cmp);
ans = right = 0;
flag = 1;
i = 0;
while (flag <= T) {
for (; i < N && E[i].u <= flag; ++i)
if (E[i].u <= flag && E[i].v > right)
right = E[i].v;
if (right >= flag) flag = right + 1, ++ans;
else break;
}
if (flag <= T) ans = -1;
printf("%d\n", ans);
}
return 0;
}
至于下面这一道题
当时看完题目头都大了,测试样例都没有过。。。所以留下大佬的ac代码与大家共同学习。
#include <bits/stdc++.h>
#define ll long long
#define time mytime
using namespace std;
const int N = 1e5;
set<pair<ll,int> > set1,set2;
int n,m;
ll bounty,increase,damage;
ll max_h[N+10],start_h[N+10],regen[N+10];
ll time[N+10],enemy[N+10],health[N+10],dic[N+10],delta = 0;
bool special[N+10];
int main(){
ios::sync_with_stdio(0),cin.tie(0);
memset(dic,255,sizeof dic);
cin >> n >> m;
cin >> bounty >> increase >> damage;
for (int i = 1;i <= n;i++){
cin >> max_h[i] >> start_h[i] >> regen[i];
if (start_h[i]>damage) continue;
if (max_h[i]<=damage ||(start_h[i]<=damage && regen[i]==0)){
special[i] = 1;
delta++;
continue;
}
ll time = (damage-start_h[i])/regen[i];
dic[i] = time;
set1.insert({time,i});
}
for (int i = 1;i <= m;i++){
cin >> time[i] >> enemy[i] >> health[i];
set2.insert({time[i],i});
}
ll ans = 0;
int pre = -1;
ll prenum = 0;
while (!set1.empty() || !set2.empty()){
ll t1 = -1,t2 = -1;
if (!set1.empty()) t1 = (*set1.begin()).first;
if (!set2.empty()) t2 = (*set2.begin()).first;
//等于的话先处理更新的
if (t1!=-1 &&(t2==-1 || t1 <t2)){
ll time2 = (*set1.begin()).first;
ll num = (ll)set1.size();
if (pre!=-1 && time2==pre){
num = prenum;
}else {
pre = time2;
prenum = num;
}
ans = max(ans,(num+delta)*(bounty+t1*increase));
set1.erase(set1.begin());
}else{
ll num = (ll)set1.size();
ans = max(ans,(num+delta)*(bounty+(t2-1)*increase));
int tempidx = (*set2.begin()).second;
set2.erase(set2.begin());
int idx =enemy[tempidx];
auto it = set1.upper_bound({dic[idx],idx});
if (it!=set1.begin()){
it--;
pair<ll,int> temp = (*it);
if (temp.first==dic[idx] && temp.second==idx){
set1.erase(it);
}
}
if (special[idx]) delta--;
special[idx] = 0;
dic[idx] = -1;
if (health[tempidx]>damage) continue;
if (max_h[idx]<=damage ||(health[tempidx]<=damage && regen[idx]==0)){
special[idx] = 1;
delta++;
continue;
} else{
ll time1 = (damage-health[tempidx])/regen[idx];
dic[idx] = time[tempidx] + time1;
set1.insert({dic[idx],idx});
}
}
}
int cc =0;
for (int i = 1;i <= n;i++)
if (special[i])
cc++;
if (cc>0 && increase>0)
return cout<<-1,0;
else ans = max(ans,(ll)cc*bounty);
cout << ans << endl;
return 0;
}
-7.7 共勉