A. Restoring Three Numbers
题意:给出4个数,它们分别是 a+b,a+c,b+c,a+b+c,求a,b,c的值
思路:排序,前三个数两两相加减去第四个数可依次求得a,b,c的值
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=200;
int main()
{
int x[5];
for(int i=0;i<4;i+=1){
scanf("%d",&x[i]);
}
sort(x,x+4);
int a=x[0]+x[1]-x[3];
int b=x[0]+x[2]-x[3];
int c=x[3]-a-b;
printf("%d %d %d\n",a,b,c);
return 0;
}
B. Make Them Equal
题意:给你一个序列,问你是否可以选取一个最小的数使得序列中的每个元素加上或减去这个数(或不变)最终能使序列中的各个元素相等
思路:
假设一个序列能找到一个数D,序列经过操作并且元素值都等于x,则原序列中的元素值最多只存在三种情况:
1)ai=x-D
2)ai=x+D
3)ai=x
解题步骤如下:
- 对序列进行去重并排序,能发现若去重后的序列中元素的个数若>3,则不存在符合条件的D;
- 若序列元素个数为3,若c-b=b-a,则D=c-b;
- 若序列元素个数为2,如果b-a是奇数,则D=b-a;若b-a是偶数,则D=(b-a)/2;
- 若序列个数为1,则D=0;
#include<bits/stdc++.h>
using namespace std;
const int N=200;
int main()
{
int n,x;
vector<int> v;
scanf("%d",&n);
int vis[N];
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i+=1){
scanf("%d",&x);
if(!vis[x])
{
vis[x]=1;
v.push_back(x);
}
}
sort(v.begin(),v.end());
if(v.size()>3)
printf("-1\n");
else if(v.size()==3)
{
if(v[2]-v[1]==v[1]-v[0])
printf("%d\n",v[2]-v[1]);
else
printf("-1\n");
}
else if(v.size()==2)
{
if((v[1]-v[0])%2)
printf("%d\n",v[1]-v[0]);
else
printf("%d\n",(v[1]-v[0])/2);
}
else
printf("0\n");
return 0;
}
C. Gourmet Cat
题意:Polycarp的猫每天会吃一样特定的食物,一、四、七吃鱼;二、六吃兔;三、五吃鸡;现在Polycarp手上分别有a,b,c份量的三种食物。他打算出去旅行,问你选择周几出行,能维持喂猫的天数最长?
思路:
1.先算出不考虑选择周几出发能喂猫的最长周期数 weeks=min({a/3,b/2,c/2})
2.从周日到周一,依次计算选择不同出发时间能维持的最长天数+7*weeks
#include<bits/stdc++.h>
using namespace std;
int main()
{
vector<int> u(3),v(3);
cin>>u[0]>>u[1]>>u[2];
int full=min({u[0]/3,u[1]/2,u[2]/2});
u[0]=u[0]-3*full;
u[1]=u[1]-2*full;
u[2]=u[2]-2*full;
vector<int> idx({0,1,2,0,2,1,0});
int ans=0;
for(int i=0;i<7;i+=1)
{
int s=i;
v=u;
int Count=0;
while(v[idx[s]]>0)
{
--v[idx[s]];
s=(s+1)%7;
Count+=1;
}
ans=max(ans,full*7+Count);
}
printf("%d\n",ans);
return 0;
}
D. Walking Robot
题意:在一个一维坐标轴上,坐标上每个点都处在光照或黑暗中,一个机器人从0出发,能到达最远的地方是n。它有一颗电池还有一颗蓄电池。机器人每次移动能选择消耗其中一颗电池中的能源。如果机器人消耗电池中的电并且移动到一个处于光照的点上,那么机器人可以给蓄电池充一个单位的电量,前提是蓄电池中的电不能超过上限。问机器人能走到的最远距离是多少?
思路: 对每一步贪心,详情看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int seg[N];
int main()
{
int n,i,bat,acc;
scanf("%d %d %d",&n,&bat,&acc);
for(i=1;i<=n;i+=1){
scanf("%d",&seg[i]);
}
int A=acc;
int B=bat;
for(i=1;i<=n;i+=1){
if(seg[i]==1)
{
if(acc==A)
acc--;
else if(bat>0)
{
bat--;
acc<A?acc=acc+1:acc;
}
else if(acc>0)
acc--;
else
break;
}
else
{
if(acc>0)
acc--;
else if(bat>0)
bat--;
else
break;
}
}
printf("%d\n",i-1);
return 0;
}
E. Two Teams
题意:有n个学生排成一列,他们各自有不同的能力数值。现在有两个教练,每个教练会选取一些学生加入他们的队伍,选取规则是:两个教练依次在还未分配队伍的学生里,先选取能力值最高的那名学生再以他为中心向两边选离他距离<=k的学生,直到所有学生被选完,输出最后每个学生的归属队伍。
思路:利用链表做删除操作,同时标记出队学生归属的队伍
#include<bits/stdc++.h>
using namespace std;
#define reset(x,y) memset(x,y,sizeof(x))
typedef long long ll;
const int N = 200005;
pair<int,int> a[N];
list< pair <int,int> > L;
list< pair <int,int> >::iterator it[N];
int vis[N],res[N];
int main()
{
int n,k,tech=1;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i].first);
a[i].second=i;
L.push_back(a[i]);
it[i]=--L.end();
}
sort(a+1,a+1+n);
reset(vis,0);
for(int i=n;i>=1;i--){
int no=a[i].second;
if(vis[no]) continue;
list< pair <int,int> >::iterator l=it[no],r=it[no];
int T=k;
while(T--)
{
if(l!=L.begin())
l--;
if(r!=--L.end())
r++;
}
r++;
while(l!=r)
{
vis[l->second]=1;
res[l->second]=tech;
l=L.erase(l);
}
tech=3-tech;
}
for(int i=1;i<=n;++i){
printf("%d",res[i]);
}
return 0;
}
F. Shovels Shop
思路:
首先要使花费最少,那么应该购买的商品应该是将价格从小到大排序的前K个商品;
关于优惠券的使用,应该选择购买同样数量商品前提下能减免的数量最多的那一张;
#include<bits/stdc++.h>
using namespace std;
#define reset(x,y) memset(x,y,sizeof(x))
typedef long long ll;
const int N = 200005;
const int INF=1e9;
int main()
{
ios::sync_with_stdio(false);
int n,m,k;
cin>>n>>m>>k;
vector<int> v(n);
for(int i=0;i<n;++i){
cin>>v[i];
}
sort(v.begin(),v.end());
v.resize(k);
reverse(v.begin(),v.end());
vector<int> offer(k+1);
for(int i=0;i<m;++i)
{
int x,y;
cin>>x>>y;
if(x<=k)
offer[x]=max(offer[x],y);
}
vector<int> pre(k+1,0);
for(int i=0;i<k;++i){
pre[i+1]=pre[i]+v[i];
}
vector<int> dp(k+1,INF);
dp[0]=0;
for(int i=0;i<k;++i)
{
dp[i+1]=min(dp[i+1],dp[i]+v[i]);
for(int j=1;j<=k;++j)
{
if(offer[j]==0)
continue;
if(i+j>k) break;
dp[i+j]=min(dp[i+j],dp[i]+pre[i+j-offer[j]]-pre[i]);
}
}
cout<<dp[k]<<endl;
return 0;
}