国王游戏
- 贪心策略:大胆假设小心求证
- 从样例出发:
- 不难看出除第一次外小涵选择 都是行或者列中最大的
- 由于电脑永远会选走能构成最大的组合->对于这一行或列:小涵永远选到的是第二大的组合&&电脑也拿不到最大的组合->使得小涵的默契值最大的话:永远选择的是第二大的组合
- 贪心策略:小涵永远选择能第二大的组合的数(由于行列对称 先选行还是列无影响)
- 答案就是所有数中第二大的数
- 贪心证明:电脑拿不到最大的组合&&小涵拿到第二大 所以小涵永远拿到的是最大的且一定赢过电脑
#include<iostream>
#include<algorithm>
using namespace std;
int map[505][505];
int main()
{
int n;
cin>>n;
int max=0;
for(int i=1;i<n;i++)
{
for(int j=i+1;j<=n;j++)
{
cin>>map[i][j];//构建样例解释用的图
map[j][i]=map[i][j];
}
}
//找出第二大的数!!
for(int i=1;i<=n;i++)
{
sort(map[i]+1,map[i]+1+n);//找出每一行第二大的数
if(max<map[i][n-1])
max=map[i][n-1];//找出第二大的数
}
cout<<"1"<<endl<<max;
return 0;
}
独木桥
- 两个问:最小&&最大
- 最小:
- 所有人朝着最快到达的方向走【此时一定不会反向】
- 同时进行:max{到达两边最快的时间}->找出最大的最小
- 最大
- 两个人反向->从宏观上看并没有改变方向【可以直接看成两个人交叉走过】->所有人朝着最慢到达的方向走
- 同时进行:max{最慢的时间}->找出最大的最大
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int l;
cin>>l;
int n;
cin>>n;
int a[5005],b[5005],c[5005];
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i]=min(a[i],l+1-a[i]);//最小
c[i]=max(a[i],l+1-a[i]);//最小
}
sort(b+1,b+1+n);//最大的最小
sort(c+1,c+1+n);//最大的最大
cout<<b[n]<<" "<<c[n];
return 0;
}
排队接水
- 每个人的等待时间是前面的人打水的时间和->对于总时间相当于第一人打水时间的n-1 +…;
- 要使越前打水的人时间越短->从小到大排序
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
long long sum=0,a[1005],b[1005];
cin>>t;
for(int i=1;i<=t;i++)
{
cin>>a[i];
b[i]=a[i];
}
sort(a+1,a+1+t);
for(int i=1;i<=t;i++)
{
if(i!=t)
sum+=a[i]*(t-i);
for(int j=1;j<=t;j++)
{
if(a[i]==b[j])
{
cout<<j;
b[j]=0;
break;
}
}
if(i!=t)
cout<<" ";
}
cout<<endl;
printf("%0.2f",sum*1.0/t);
return 0;
}
合并果子
- 题目很简单:留意一项优先队列的用法
- 每两个和就是体力和:找到最小的合并【记得更新】每执行一次更新一次->使用优先队列更方便
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
priority_queue<int,vector<int>,greater<int> > q;
for(int i=1;i<=n;i++)
{
int a;
cin>>a;
q.push(a);
}
int nz;
int ans=0;
while(!q.empty())
{
int nx=q.top();
q.pop();
int ny=q.top();
if(!q.empty())
{
ny=q.top();
q.pop();
}
else continue;
ans+=nx+ny;
q.push(nx+ny);
}
cout<<ans;
}