Benelux Algorithm Programming Contest

A题:
从n个中取k个数字,使得这k个数字中,两两相加小于等于m。求最大的k。
考虑sort一遍n个数字,因为次大加上最大值如果小于m,那么说明这个最大是可以选取的,ans++。直到找到了一个次大和最大,相加大于了k,停止,因为只要这两个数字不大于k,集合里面的所有数字都不大于k了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define up(i,a,n) for(int i=a;i<=n;i++)
const int maxn=1e5+10;
ll arr[maxn];
int main()
{
	long long n,m;
	scanf("%lld %lld",&n,&m);
	up(i,1,n)scanf("%lld",&arr[i]);	
    if(n==1)
    {
        cout<<1<<endl;
        return 0;
    }
	sort(arr+1,arr+1+n);
	long long ans=0;
	long long now=m;
	for(int i=1;i<=n;i++)
	{
		if(arr[i]<=now)
        {
            ans++;
            now=m-arr[i];
        }
        else break;
	}
	if(ans!=0)
	printf("%lld",ans);
	else printf("1");
    return 0;
}

B题
模拟题。找到与当前给出来的日期相距最远的一个日期。
队友写的 ,大概这个意思吧。。

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define up(i,a,n) for(int i=a;i<=n;i++)
const int maxn=150;
int d[12]={0,31,59,90,120,151,181,212,243,273,304,334};
int da[12]={31,28,31,30,31,30,31,31,30,31,30,31};
struct node
{
	int month,day,num;
}arr[maxn];
int cmp(node a,node b)
{
	return a.num<b.num;
}
int main()
{   
	int n;
	scanf("%d",&n);
	string s;
	up(i,1,n)
	{
		cin>>s;
		scanf("%02d-%02d",&arr[i].month,&arr[i].day);
		arr[i].num=d[arr[i].month-1]+arr[i].day;
	}
	sort(arr+1,arr+1+n,cmp);
	int now=arr[1].num+(365-arr[n].num)-1;
	int now2=d[9]+28;
	int now3=arr[1].num-now2;
	if(now3<0)now3+=365;
	int ans=1;
	for(int i=2;i<=n;i++)
	{
		if(arr[i].num-arr[i-1].num-1>now)
		{
			now=arr[i].num-arr[i-1].num-1;
			ans=i;
		}
		else if(arr[i].num-arr[i-1].num-1==now)
		{
	       int d1=arr[i].num-now2;
	       if(d1<=0)d1+=365;
	       if(d1<now3)
	       {
	       	ans=i;
	       	now3=d1;
		   }
		}
	}
	if(arr[ans].day!=1)printf("%02d-%02d",arr[ans].month,arr[ans].day-1);
	else if(arr[ans].month!=1)
	{
	printf("%02d-%02d",arr[ans].month-1,da[arr[ans].month-2]);
    }
    else if(arr[ans].month==1&&arr[ans].day==1)
    {
    	printf("12-31");
	}
}

c题。
题目要求给一个长方形的箱子,无缝隙的可以放入n个111的cube,问最小表面加。
枚举边长,得到高,不断计算更新min值。

#include<iostream>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
int read()
{
	char ch = getchar(); int x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
int v;
int main()
{
	v = read();
	ll ans = 1e18;
	upd(i, 1, v)
	{
		if (v%i == 0)
		{
			int chang = v / i;
			upd(j, 1, chang)
			{
				if (chang%j == 0)
				{
					int kuan = chang / j;
					ans = min(ans, (ll)(2 * i*j + 2 * kuan*i + 2*kuan*j));
				}
			}
		}
	}
	cout << ans << endl;
	return 0;
}

J题 数学题。
海伦公式的变形(题目保证了了有解)
对一般四边形的面积,扩展的婆罗摩笈多公式用到了四边形的对角和:
在这里插入图片描述

#include<iostream>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
int read()
{
	char ch = getchar(); int x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
double a, b, c, d;
int main()
{
	cin >> a >> b >> c >> d;
	double s = (a + b + c + d) / 2.0;
	printf("%.8lf", (double)sqrt((s - a)*(s - b)*(s - c)*(s - d)));
	return 0;

}

F题。
给出代价和每天赚的钱数,求最小天数,赚到k。
队友写的,用每天赚的除以需要赚的,玄学代码。
其实这道题二分就可以了,因为转的钱每天都在增加,所以某一天刚好可以了,后面所有天都可以了。
于是我们二分天数,对于每一个天数,带回去验证,赚的钱乘以天数-付出,大于零就记录下来
最后和需要赚的钱比较一下,就知道是否是我们要的了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define up(i,a,n) for(int i=a;i<=n;i++)
const int maxn=1e5+10;
struct node
{
	ll in,out,day;
}arr[maxn];
int cmp(node a,node b)
{   
	return 1.0*a.out/a.in>1.0*b.out/b.in;
}
int main()
{
	long long  n,m;
	scanf("%lld %lld",&n,&m);
	up(i,1,n)
	{
		scanf("%lld %lld",&arr[i].out,&arr[i].in);
	}
	sort(arr+1,arr+1+n,cmp);
	double now=1.0*arr[1].out/(arr[1].in+m);
	ll fz=arr[1].out;
	ll fm=arr[1].in+m;
	up(i,2,n)
	{
		ll dz=fz+arr[i].out;
		ll dm=fm+arr[i].in;
		double fs=1.0*dz/dm;
		double fs1=1.0*arr[i].out/(arr[i].in+m);
		if(fs>now&&fs>fs1)
		{
			fz=dz;
			fm=dm;
		}
		else if(fs1>now&&fs1>fs)
		{
			fz=arr[i].out;
			fm=arr[i].in+m;
		}
		now=1.0*fz/fm;
	}
	ll ans=ceil(1.0*fm/fz);
	cout<<ans<<endl;
}

ps 这种类似于除法的规划问题,一般都用二分,这代码好玄学。。


G题,暴力模拟。
题意就是找出最小的移动代价,使得序列中ABC都是连在一起的。
枚举情况,有六种,abc,acb,cab,cba,bac,bca
但其实只有两种情况,abc和acb,因为他是个环,其他所有情况都是这两种情况的变形。
我们先把数组拉长。以保证环。
然后对于长度为len的字符串,不断尺取法加上差分思想去更新代价。
即,先对于原字符串,跑一遍代价,然后区间向有移动一格,然后对于每个小区间,0-a,a-a+b,a+b-a+b+c的端点,判断右移动一格后,出现的代价。

#include<iostream>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
int read()
{
	char ch = getchar(); int x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
int len;
string s;
string ss;
int A, B, C;
int judge(string s2)
{
	int res = 0;
	up(i, 0, len)
	{
		if (s2[i] != ss[i])res++;
	}
	return res;
}
int main()
{
	len = read();
	cin >> s;
	up(i, 0, len)
	{
		if (s[i] == 'A')A++;
		else if (s[i] == 'B')B++;
		else C++;
	}
	ss = s;
	s += ss;
	string temp="";
	up(i, 0, A)temp += 'A';
	up(i, 0, B)temp += 'B';
	up(i, 0, C)temp += 'C';
	int ans = INF;
	int ans1 = judge(temp);
	ans = min(ans, ans1);
	upd(i, 1, len-1)
	{
		if (s[i - 1] == 'A')ans1++;
		if (s[i - 1 + A] == 'A')ans1--;
		if (s[i - 1 + A] == 'B')ans1++;
		if (s[i - 1 + A + B] == 'B')ans1--;
		if (s[i - 1 + A + B] == 'C')ans1++;
		if (s[i - 1 + A + B + C] == 'C')ans1--;
		ans = min(ans, ans1);
	}
	temp.clear();
	up(i, 0, A)temp += 'A';
	up(i, 0, C)temp += 'C';
	up(i, 0, B)temp += 'B';
	int ans2 = judge(temp);
	ans = min(ans, ans2);
	upd(i, 1, len - 1)
	{		
		if (s[i - 1] == 'A')ans2++;//整个区间右移动一格后,新的费用
		if (s[i - 1 + A] == 'A')ans2--;
		if (s[i - 1 + A] == 'C')ans2++;
		if (s[i - 1 + A + C] == 'C')ans2--;
		if (s[i - 1 + A + C] == 'B')ans2++;
		if (s[i - 1 + A + B + C] == 'B')ans2--;
		ans = min(ans, ans2);
	}
	cout << ans << endl;
	return 0;
}

K题,任意删去有根树的一条边,使得任何点都可以到根节点。
贪心。
其实只要把叶子节点全部连接起来,就可以使得每个点都在某一个环内。
注意特判,如果根节点只有一个出度,那么根节点也要和叶子节点连接起来,不然删掉那一条边,根节点就gg了。
dfs找叶子节点记录下来。

#include<iostream>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
int read()
{
	char ch = getchar(); int x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
int val[100005], out[100005];
vector<int >g[100005];
vector<int >ans;
int n, h;
void dfs(int root, int f)
{
	if (val[root] == 1)ans.push_back(root);
	up(i, 0, g[root].size())
	{
		if (g[root][i] != f)
		{
			dfs(g[root][i], root);
		}
	}
}
int main()
{
	n = read();
	h = read();
	int a, b;
	up(i, 0, n - 1)
	{
		a = read();
		b = read();
		g[a].push_back(b);
		g[b].push_back(a);
		val[a]++;
		val[b]++;
	}
	dfs(h, -1);
	int temp = (ans.size()+1) / 2;
	cout << temp << endl;
	up(i, 0, ans.size() / 2)
	{
		cout << ans[i] << " " << ans[i + ans.size()/2] << endl;
	}
	if (ans.size() & 1)cout << ans.back() <<" "<<ans[0] << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44019404/article/details/89818877