奋斗群群群赛—13,14
群赛13
T1:Dima and Guards
题目位置:
题意:
就是有四个守卫,你需要贿赂一行的守卫,每行有2个守卫,有4个数据,分别是守卫1的蛋糕和茶水的值和守卫2的,,,如果输入的数据的钱数能够贿赂,就是出方案的花费!
AC代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,flag=0,loc=0,x,y,min1;
scanf("%d",&n);
for(int i=1; i<=4; i++)
{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
x=min(a,b);
y=min(c,d);
if(x+y<=n&&flag==0)
{
min1=x;
loc=i;
flag=1;
}
}
if(flag==1)
{
printf("%d %d %d\n",loc,min1,n-min1);
}
else
printf("-1\n");
return 0;
}
小反思:
无…
T2:Dima and To-do List
题目位置:
题意:
就是每次取物品隔着m个数来取,求输出的最大的和值的情况的初始的点的位置.
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int N=100005;
int a[N];
long long t[N];
int main()
{
int n,m,tot,loc;
int max=999999999;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
}
for(int i=1; i<=m; i++)
{
int ans=0;
for(int j=i; j<=n; j+=m)
{
ans+=a[j];
}
if(ans<max)
{
max=ans;
loc=i;
}
}
printf("%d\n",loc);
return 0;
}
T3:Dima and Salad
题目位置:
题意:
有n个蛋糕,输入了第一行是各个蛋糕的美味值ai,接下来是花费值bi,求使得能让取了m个蛋糕的美味值的总和除以m个蛋糕的花费之总和为k!
求最大的美味值总和,并且输出∑ai的知就好了!
想法:
就是将a[i]的值每次都减去k*b[i],就相当于是分离正系数的一个做法,就像这样:
for(int i=1; i<=n; i++)
{
x[i]=a[i]-k*b[i]; // + ´óÁË! // - С ÁË!
}
在就会得到一些有正有负的x[i]数组,只要选取将其和为0 的数据就是可以了!因为这时候就是可以整除,因为互补嘛!
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int N=10005;
int a[N],b[N],x[N];
int dp[105][N];
int main()
{
int n,k;
scanf("%d%d",&n,&k);
int V=n*100;
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
for(int i=1; i<=n; i++)
scanf("%d",&b[i]);
memset(dp,192,sizeof(dp));
dp[0][V]=0;
//x Ëù´æ´¢µÄÖµ¾ÍÊÇÒ»¸öËùνµÄÀíÏ뻯ֵ , ¶øÕý¸º±íʾÁËÆä ´óСÓë·ñ!
for(int i=1; i<=n; i++)
{
x[i]=a[i]-k*b[i]; // + ´óÁË! // - С ÁË!
}
for(int i=1; i<=n; i++)
{
for(int j=2*V; j>=0; j--)
dp[i][j]=max(dp[i-1][j],dp[i-1][j-x[i]]+a[i]);
}
printf("%d\n",dp[n][V]?dp[n][V]:-1);
return 0;
}
T4:
题目位置:
题意:
有n个点m条无向边。初始你需要选择一个整数x,走第i条边的限制为Li <= x <= Ri,假设1-n的一条路径上可以选择的整数x有ans,问你最大的ans。
(所以说就是并查集,加上一个暴力枚举就好了!)
AC代码
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=2003;
int fa[N],ans;
struct tree
{
int end,start,l,r;
} t[3005];
bool com(tree x,tree y)
{
return x.l<y.l?true:false;
}
int find(int x)
{
return fa[x]==x?x:fa[x]=find(fa[x]);
}
void add(int x,int y)
{
fa[find(x)]=find(y);
}
bool judge(int x,int y)
{
if(find(x)==find(y))
return true;
else
return false;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++)
{
scanf("%d%d%d%d",&t[i].start,&t[i].end,&t[i].l,&t[i].r);
}
sort(t+1,t+1+m,com);
for(int i=1; i<=m; i++)
{
//只是当做 t[i].r 为最大的上限就好了!
for(int j=1; j<=n; j++)
fa[j]=j;
for(int j=1; j<=m; j++)
{
if(t[j].l>t[i].r)
break;
if(t[j].r<t[i].r)
continue;
add(t[j].end,t[j].start);
if(judge(1,n))
{
ans=max(ans,t[i].r-t[j].l+1);
break;
}
}
}
ans?printf("%d\n",ans):printf("Nice work, Dima!\n");
return 0;
}
小反思:
就是相当于一些大大小小的水管一样的,每个数据都有上限和下限,所以就是问你,有多少的水流能够一次性流到底:那么就是变成了想法就是枚举一个数据的下限!就是a[i].r的值,表示我每次只是去比它大的值,别的不去,就是这个思路了!
T5:Dima and Magic Guitar
题目位置:
题意:
就是求曼哈顿最远距离……
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int N=20005;
int f[N][10];
int main()
{
int n,m,k,len,x;
scanf("%d%d%d%d",&n,&m,&k,&len);
//Ö÷ҪʹµÃ ¼õºÅÇ°µÄ¾¡Á¿µÄ´ó ¼õºÅºóµÄ¾¡Á¿Ð¡!
for(int i=1;i<=k;i++)
{
f[i][1]=f[i][2]=-99999;
f[i][3]=f[i][4]=99999;
}
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
{
scanf("%d",&x);
f[x][1]=max(f[x][1],i+j);
f[x][2]=max(f[x][2],i-j);
f[x][3]=min(f[x][3],i+j);
f[x][4]=min(f[x][4],i-j);
}
int sta,end,ans=0;
scanf("%d",&sta);
for(int i=2; i<=len; i++)
{
scanf("%d",&end);
ans=max(f[sta][1]-f[end][3],ans);
ans=max(f[end][2]-f[sta][4],ans);
ans=max(f[sta][2]-f[end][4],ans);
ans=max(f[end][1]-f[sta][3],ans);
sta=end;
}
printf("%d\n",ans);
return 0;
}
小反思:
one:
(x1-x2) + (y1-y2) ---> (x1+y1) - (x2+y2)
two:
-(x1-x2) + (y1-y2) ---> (x2-y2) - (x1-y1)
three:
(x1-x2) - (y1-y2) ---> (x1-y1) - (x2-y2)
four:
-(x1-x2) - (y1-y2) ---> (x2+y2) - (x1+y1)
群赛14:
T1:Compote
题目位置:
题意:
不说了,直接上代码!
AC代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
a/=1;
b/=2;
c/=4;
int tot=min(min(a,b),c);
printf("%d\n",tot*7);
return 0;
}
T2:Decoding
题目位置:
题意:
输入1个长度为n(1<=n<=2000)的字符串s1是由另一个长度为n的字符串s2变化而来,变化规则是:每次都把s2中间(如果长度是偶数就取小的一个)的字母拿出放到s1的第一个上,由此反复进行直到取完。要求输出s2这个字符串。
AC代码:
找规律!!!
#include<bits/stdc++.h>
using namespace std;
const int N=2005;
char a[N],s[N];
int main()
{
int n;
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
cin>>a[i];
}
if(n%2==1)
{
int j=n/2+1;
s[j]=a[1];
for(int i=1;i<=n/2;i++)
{
s[j-i]=a[i*2];
s[j+i]=a[i*2+1];
}
for(int i=1;i<=n;i++)
cout<<s[i];
}
else
{
int j=n/2;
s[j]=a[1];
for(int i=1;i<=n/2;i++)
{
s[j+i]=a[i*2];
if(j-i>0)
s[j-i]=a[i*2+1];
}
for(int i=1;i<=n;i++)
cout<<s[i];
}
}
T3:Tram
题目位置:
题意:
在一条直线上,坐标从0到S。 人要从X1位置向X2位置移动,前进一个单位要t2时间。 当人在X1位置,车子在p位置,前进一个单位要t1秒。方向为d,d==1表示从正方向前进, d == -1表示负方向前进。 人可以在与车子相遇时,坐上车子。
AC代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int s,x1,x2;
int t1,t2;
int p,d;
scanf("%d%d%d%d%d%d%d",&s,&x1,&x2,&t1,&t2,&p,&d);
int time=abs(x2-x1)*t2; //ͽ²½ÐÐ×ßµÄtime!
// int car=time/t1; // Æû³µ×î¶à×ßÁ˶àÉÙ!
// int tiss car
int tot1,tot2;
tot1=time;
if(d==1)
{
if(p<=x1&&x1<x2)
tot2=(x2-p)*t1;
else if(x2>x1)
tot2=(2*s+x2-p)*t1;
else if(x2<x1)
tot2=(2*s-x2-p)*t1;
}
else
{
if(p>=x1&&x2<x1)
tot2=(p-x2)*t1;
//x1 x2
else if(x2<x1)
tot2=(p+2*s-x2)*t1;
else if(x1<x2)
tot2=(p+x2)*t1;
}
if(tot2>tot1)
cout<<tot1<<endl;
else
cout<<tot2<<endl;
return 0;
}
小反思:
这道题目的关键就是抓住车到终点的时间和人到达终点的时间的min值!
就是这么妙的题目!
T4:Green and Black Tea
题目位置:
题意:
就是喝红茶和黑茶,每次不能够连续喝k次,输出喝茶的方案就好!
AC代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,k,a,b;
scanf("%d%d%d%d",&n,&k,&a,&b);
// a Â̲è G
// b ºÚ²è B
int maxn=max(a,b);
int minn=min(a,b);
if((maxn-1)/k>minn)
{
cout<<"NO";
return 0;
}
if(a<=b)
{
int cha=b-a;
while(cha>k-1&&b>=k&&a>0)
{
b-=k;
a--;
for(int i=1; i<=k; i++)
cout<<"B";
cout<<"G";
cha=b-a;
}
for(int i=1; i<=cha; i++)
{
cout<<"B";
b--;
}
for(int i=1; i<=a+b; i+=2)
cout<<"G"<<"B";
}
else
{
int cha=a-b;
while(cha>k-1&&a>=k&&b>0)
{
a-=k;
b--;
for(int i=1; i<=k; i++)
cout<<"G";
cout<<"B";
cha=a-b;
}
for(int i=1; i<=cha; i++)
{
cout<<"G";
a--;
}
for(int i=1; i<=a+b; i+=2)
cout<<"B"<<"G";
}
}