第六届福建省赛

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;
}



猜你喜欢

转载自blog.csdn.net/b_r_e_a_d/article/details/80245732
今日推荐