九度oj 王道论坛研究生机试练习赛第三场

本文介绍了ACM竞赛中的两道典型题目:切蛋糕与座位安排问题。首先深入分析了切蛋糕问题的几何原理,通过逐步推导公式,最终采用二分查找法求解刀痕长度。接着讲解了座位安排问题,巧妙地运用动态规划解决复杂排列组合问题,优化时间复杂度至O(n)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

昨晚做了九度oj上的练习赛。。

让我感觉这些题目对于acm来说真是心不难。。

好了,闲话少说,就给出最后两道的题解。

题目1551:切蛋糕

时间限制:1 秒

内存限制:128 兆

特殊判题:

提交:236

解决:71

题目描述:

有如下图半价为R的圆形蛋糕,被切一刀后(图中红色直线),分成两个部分(黄色和绿色),已知其比例为r,求刀痕长度(图中红色直线)。

输入:

输入包括多组测试数据,包括一个整数R(1<=R<=1000),和一个浮点数r(0<r<1),精确到第四位小数。

输出:

对于每组测试用例,输出一个浮点数,代表刀痕的长度,保留二位小数。

样例输入:
1000 0.5000
500 0.6183
样例输出:
1928.53
982.49
来源:
2014年王道论坛研究生机试练习赛(三)
这道是我见过的最纯粹的几何题。

首先是要靠你一步一步推出公式

假设半径为R,比例为f

S为圆的面积

q为切线交点和圆心的连线的角度的一半

然后可知切割后的一部分面积为x = (f*S)/(f+1)

然后R^2*q - R^2*sin(2*q)/2 = x

对于这条方程最主要就是求出q的值,但是~~我不会

所以我就用最简单的方法求:二分求值

然后ans = 2.0*R*sin(mid)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<math.h>

using namespace std;
#define pi 3.1415926
int main()
{
    int n,i,j;
    int sum;
    double R,f;
	while(~scanf("%lf%lf",&R,&f))
	{
		double S = R*R*pi;
		if(f>1.0)
		f = 1.0/f;
		double var = (f*S)/(f+1.0)/(R*R) ;
		double l = 0,r = pi/2.0,mid;
		while(1)
		{
			mid = (l+r)/2.0;
			if(mid-sin(2.0*mid)*0.5>var)
			r = mid;
			else
			l = mid;
			if(r-l<0.00000001)
			break;
		}
		
		printf("%0.2f\n",2.0*R*sin(mid));
	}
    return 0;
	
}

————————————————————————————————————————————————————————————

————————————————————————————————————————————————————————————

题目1552:座位问题

时间限制:1 秒

内存限制:128 兆

特殊判题:

提交:227

解决:60

题目描述:

计算机学院的男生和女生共n个人要坐成一排玩游戏,因为计算机的女生都非常害羞,男生又很主动,所以活动的组织者要求在任何时候,一个女生的左边或者右边至少有一个女生,即每个女生均不会只与男生相邻。现在活动的组织者想知道,共有多少种可选的座位方案。


例如当n为4时,共有
女女女女, 女女女男, 男女女女, 女女男男, 男女女男, 男男女女, 男男男男
7种。

输入:

输入包含多组测试用例,每组测试用例仅包含一个整数n(1<=n<=1000)。

输出:

对于每组测试用例,输出一个数代表可选的方案数,为防止答案过大,答案对1000000007取模。

样例输入:
1
2
4
样例输出:
1
2
7
来源:
2014年王道论坛研究生机试练习赛(三)
最后一题,一看到这种题目就应该想到动态规划

不过哥状态方程我也想了很久,丢脸!~~~

dp[i][j]表示第i个放男和女的个数(j为0是男,j为1是女)

然后很容易dp[i][0] = dp[i-1][0]+dp[i-1][1];

关键就是dp[i][1]这么表示

其实dp[i][1] = sum(dp[k][0])(k = 0~i-2)

其实意思就是最后一个放女的那倒数第二个就一定也是女的但是男的最后一个放在那里呢

就是枚举最后一个男的位置

把所有的情况都考虑了一遍

这个操作可以用单调队列来实现

最后时间复杂度就变成里O(n)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<math.h>
 
using namespace std;
#define MOD 1000000007
int dp[1005][3];
void Init()
{
    int i,j;
    memset(dp,0,sizeof(dp));
    dp[1][0] = 1;
    dp[1][1] = 0;
    dp[0][0] = 1;
    //dp[2][]
    int sum = 0;
    for(i=2;i<1003;i++)
    {
        dp[i][0] = (dp[i-1][0]+dp[i-1][1])%MOD;
        sum = (sum+dp[i-2][0])%MOD;
        dp[i][1]=(dp[i][1]+sum)%MOD;
        
    }
     
}
int main()
{
    int n,i,j;
    Init();
    while(~scanf("%d",&n))
    {   
        printf("%d\n",(dp[n][0]+dp[n][1])%MOD);
    }
    return 0;
     
}


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值