A. Cow and Haybales
题意:
有n堆草,每堆为ai,每分钟一次可以移动1个草从x到x-1或x+1。求在d分钟内,可以将第一堆的a1最大增加到多少。
思路:
从右2,3..依次枚举,要考虑距离以及是移动的最后一堆能移多少
代码:
#include<bits/stdc++.h>
using namespace std;
int a[101];
int main(){
int n,d,T;
cin>>T;
while(T--){
cin>>n>>d;
for(int i=1;i<=n;++i)
cin>>a[i];
for(int i=2;i<=n;++i){
if(d>(i-1)*a[i]){
d-=(i-1)*a[i];
a[1]+=a[i];
}
else {
a[1]+=d/(i-1);
break;
}
}
cout<<a[1]<<endl;
}
return 0;
}
B. Cow and Friend
题意:
在二维平面上Bessie在(0,0)的位置要到达(x,0),一次可以k个移动确定的距离a1,a2...ak。
思路:
先移动选择最大的距离,当第i要再走一步会超过x时,考虑在i-1 和 i步的时候走一个等腰三角形,因为这样可以构造出一个(0,2a]的任意距离。我的代码考虑了判断是否存在a可以一步正好到达(其实没啥用,和走等腰的答案一样)
代码:
#include<bits/stdc++.h>
using namespace std;
int step[100010];
map<int,int> mmp;
void solve(){
int n,x;
mmp.clear();
cin>>n>>x;
int f=0;
int Ms=0;
for(int i=1;i<=n;++i){
cin>>step[i];
if(step[i]==x) {
f=-1;
}
Ms=max(Ms,step[i]);
mmp[step[i]]=1;
}
if(f==-1) {
puts("1");
return ;
}
int res=x/Ms;
if(x%Ms==0){
}
else if(mmp[x%Ms]){
res++;
}
else if(res>0){
res+=1;
}
else
res+=2;
cout<<res<<'
';
}
int main(){
int T;
cin>>T;
while(T--){
solve();
}
return 0;
}
C. Cow and Message
题意:
给出一个字符串,求出所有的序列号为等差数列的一样的子序列的最多的数量。
例如“aaabb”,它可以按条件得到的子序列有:
a 构造方法有: (1), (2), (3)
b 构造方法有: (4), (5)
ab 构造方法有: (1,4), (1,5), (2,4), (2,5), (3,4), (3,5)
aa 构造方法有: (1,2), (1,3), (2,3)
bb 构造方法有: (4,5)
aab 构造方法有: (1,3,5), (2,3,4)
aaa 构造方法有: (1,2,3)
abb 构造方法有: (3,4,5)
aaab 构造方法有: (1,2,3,4)
aabb 构造方法有: (2,3,4,5)
aaabb 构造方法有: (1,2,3,4,5)
答案为6 ,即ab构造方法最多。
做法:可以举个例子:abc,构造ab的方法一定是大于或者等于构造abc的方法,因为构造abc会多产生了一个限制条件即c。所以我们只用考虑长度为1和2的子序列。
#include<bits/stdc++.h>
using namespace std;
char s[100010];
long long pre[30];
long long dp[30][30];
int main(){
long long ans=0;
cin>>s;
for(int i=0;s[i];++i){
for(char ch='a';ch<='z';++ch){
dp[ch-'a'][s[i]-'a']+=pre[ch-'a'];
ans=max(dp[ch-'a'][s[i]-'a'],ans);
}
pre[s[i]-'a']++;
ans=max(ans,pre[s[i]-'a']);
}
cout<<ans<<'
';
return 0;
}
D. Cow and Fields
题意:
在n个点m条边的无向图中给出k个特殊点,必须在
这k个点之间添加一条边,求如何添加得1-n的最短距离最大。
做法:很容易想到开两个数组跑两遍最短路算法,分别求每个点到1和n的最短距离。找到最大的ds[u]+dt[v]+1。然后需要考虑一个关键的限制性条件,我们选取的u,v首先满足ds[u]+dt[v]<=ds[v]+dt[u],再变换一下就是ds[u]-dt[u]<=ds[v]-dt[v]。首先我们要找的最大ds[u],且v一定是ds-dt大于u的,所以我们可以按ds-dt排个序,这样我们先选取ds[u]最大的u,后面的v一定符合条件,通过这样迭代找到ds[u]+dt[v]最大的。最后和原来的最短路做比较。
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int head[maxn],cnt;
struct ac{
int v,nex;
}edges[maxn*2];
void addedge(int u,int v){
edges[++cnt]=(ac){v,head[u]};
head[u]=cnt;
}
int a[maxn];
long long ds[maxn],dt[maxn];
bool inq[maxn];
void spfa(int st,long long dis[]){
memset(inq,0,sizeof inq);
queue<int> q;
q.push(st);
dis[st]=0;
inq[st]=1;
while(!q.empty()){
int u=q.front();q.pop();
inq[u]=0;
for(int i=head[u];~i;i=edges[i].nex){
int v=edges[i].v;
if(dis[v]>dis[u]+1){
dis[v]=dis[u]+1;
if(inq[v]==0){
inq[v]=1;
q.push(v);
}
}
}
}
}
int f[maxn];
vector<pair<int,int> > v;
int main(){
memset(head,-1,sizeof head);
cnt=0;
int n,m,k;
cin>>n>>m>>k;
for(int i=1;i<=n;++i){
ds[i]=dt[i]=10000000000000;
}
for(int i=1;i<=k;++i){
cin>>a[i];
}
for(int i=1;i<=m;++i){
int u,v;
cin>>u>>v;
addedge(u,v);
addedge(v,u);
}
spfa(1,ds);
spfa(n,dt);
for(int i=1;i<=k;++i){
v.push_back({ds[a[i]]-dt[a[i]],a[i]});
}
sort(v.begin(),v.end());
long long res=0,tmp=0;
for(int i=0;i<v.size();++i){
int u=v[i].second;
if(i!=0){
res=max(res,tmp+dt[u]+1);
}
tmp=max(tmp,ds[u]);
}
cout<<min(res,ds[n]);
return 0;
}