A:题意是有n个手机和一个充电宝,问你最多能把几个手机充满电(100%)。直接排序嘛,然后一直减就行了。
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int t;
cin>>t;
while(t--)
{
int a[111];
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
sort(a,a+n);
int ans=0;
for(int i=n-1;i>=0;i--)
{
if(m>=100-a[i])
{
ans++;
m-=100-a[i];
}
else break;
}
cout<<ans<<endl;
}
return 0;
}
B:就是判断两个圆之间有几个切线,相离4条,相切3条,相交2条,内切1条,内含0条,如果两圆相同就输出-1。
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int t;
cin>>t;
while(t--)
{
int x1,y1,r1,x2,y2,r2;
cin>>x1>>y1>>r1>>x2>>y2>>r2;
int dy=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
int dr=(r1-r2)*(r1-r2);
int drh=(r1+r2)*(r1+r2);
if(dy<dr)
{
cout<<"0"<<endl;
}
else if(dy==dr&&dr!=0)
{
cout<<"1"<<endl;
}
else if(dy==0&&r1==r2)
{
cout<<"-1"<<endl;
}
else if(dy==drh)
{
cout<<"3"<<endl;
}
else if(dy>drh)
{
cout<<"4"<<endl;
}
else cout<<"2"<<endl;
}
return 0;
}
C:01背包,根据数据范围可以知道是以价值总和做背包容量的。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
#define LL long long int
const int inf=0x3f3f3f3f;
LL dp[5050];
int w[550];
int v[550];
int main()
{
int T;
int n,b;
cin>>T;
while(T--)
{
scanf("%d%d",&n,&b);
int sum=0;
for(int i=0;i<n;i++)
{
cin>>w[i]>>v[i];
sum+=v[i];
}
memset(dp,inf,sizeof(dp));
dp[0]=0;
for(int i=0;i<n;i++)
{
for(int j=sum;j>=v[i];j--)
{
dp[j]=min(dp[j],dp[j-v[i]]+w[i]);
}
}
for(int i=sum;i>=0;i--)
{
if(dp[i]<=b)
{
cout<<i<<endl;
break;
}
}
}
return 0;
}
E:读错题目了,让我写了好大一会的最长上升子序列。。
(赛后清题)输入时先记录0的数量,用一个数组记录当前位置之前有多少空位。然后从前往后遍历位置,得到当前位置到最后位置之前能用0连接起来(覆盖)的空位长度,从中取最长的长度即可。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
#define LL long long int
int T;
int n, m, a;
int vis[100100];
int pre[100100];
int main()
{
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &n, &m);
int cmp = 0;
memset(vis, 0, sizeof(vis));
for (int i = 0; i < n; i++)
{
scanf("%d", &a);
if (!a)
cmp++;
else
vis[a] = 1;
}
memset(pre, 0, sizeof(pre));
for (int i = 1; i <= m; i++)
pre[i] = pre[i - 1] + (!vis[i]);
int res = 0;
for (int i = 1; i <= m; i++)
{
int cnt = upper_bound(pre + i, pre + m + 1, cmp + pre[i-1]) - pre;
res = max(cnt - i, res);
}
printf("%d\n", res);
}
return 0;
}
H:很巧妙的一个算法,队友写的。我现在也只是模糊的懂了,等下再仔细看看。用了一个二叉树的思想,实现的话就是用优先队列每次先取次小的(因为最小的时间会被覆盖掉的)加上工人繁殖(?)的时间,这样虽然处理是从小往大处理,但是实际上的意思是每次先让工人去修耗时最长的房子。越到后面的话,修建房子的时间就越短,但是相应的繁殖耗时就越长。(这道题优先队列里面可以直接多写一点东西让从小到大输出的,不用在结构体里面重载的)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
using namespace std;
struct node
{
int t;
bool operator < (const node & a) const
{
return t>a.t;
}
};
int main()
{
int T;
cin>>T;
while(T--)
{
int n,m,k;
priority_queue <node> q;
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<n;i++)
{
node a;
scanf("%d",&a.t);
q.push(a);
}
while(n>m)
{
q.pop();
node a=q.top();
a.t+=k;
q.push(a);
q.pop();
n--;
}
while(q.size()!=1)q.pop();
cout<<q.top().t<<endl;
}
return 0;
}
J:又是队友的代码。。我自己写的不对。。我刚开始写了大于等于第二个的1.5倍就能赢,结果wa了两发。后来队友貌似算法对但是一直没过,最后发现这个oj的输入long long int 只能用I64d不能用lld,血崩。等下看完再来说思路。
看了队友的代码发现写的有点麻烦的,自己写了一发。思路就是把前面的除以三,如果有余数就平分到其中任意一个或两个,然后取最小的两个相加再加上2得到一个值,如果后面的值大于等于这个值,就会输,不然的话就稳赢。(证明略,很简单的,自己玩一下就行了)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
#define LL long long int
int main()
{
int T;
int a, b;
cin >> T;
while (T--)
{
scanf("%d%d", &a, &b);
int cmp = a % 3;
int aa = a / 3;
int bb = a / 3;
if (cmp == 2)
aa++;
if (aa + bb + 2 <= b)
printf("No\n");
else
printf("Yes\n");
}
return 0;
}
扫描二维码关注公众号,回复:
2446406 查看本文章