UVA1073 Glenbow Museum

链接

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3514

题解

把所有的边看作直线做半平面相交得到的就是多边形内核
这题的意思就是你构造的那个多边形必须内核不为空
首先 R R 肯定比O多四个,这无可厚非,因为最终方向一定是转了 360 360 ∘
那么 R R 就有n2+2个, O O 就有n22
N N 肯定是不小于4的偶数,否则无解
考虑什么时候这个序列不合法:
如果有连续的 O O 就不行,因为这样就会出现两个没有交集的半平面,也就不存在内核了,所以O一定不连续
那么肯定会存在连续的 R R ,考虑两个R连续的时候,答案是合法的;连续三个 R R 连续的时候,依然可以构造出合法图形;连续四个R连续的时候,这样构造:
这里写图片描述
连续 5 5 R的时候,这样构造
这里写图片描述
所以最后就是要你把 n22 n 2 − 2 R R n2+2 O O 排起来,使得任意两个O不相邻

处理1

《算法竞赛入门经典训练指南》中给出了一个 DP D P
f(i,j,0/1,0/1) f ( i , j , 0 / 1 , 0 / 1 ) 表示使用 i i R j j O组成合法序列的个数,状态转移方程在下方程序里有,基本思路就是每次在结尾加入一个 0 0 1,分类讨论。

处理2

其实可以这样,先把 n22 n 2 − 2 0 0 排成一排,然后把1插空放进去,推出来公式是:

2C4n/2+1+C3n/2+1 2 C n / 2 + 1 4 + C n / 2 + 1 3

代码1

//奇妙数学+dp
#include <bits/stdc++.h>
#define ll long long
#define maxn 1010
using namespace std;
ll N, f[maxn][maxn][2][2];
void init()
{
    ll i, j;
    f[1][0][0][0]=f[0][1][1][1]=1;
    for(i=0;i<maxn;i++)for(j=0;j<maxn;j++)
    {
        if(i+j<=1)continue;
        if(i)f[i][j][0][0]=f[i-1][j][0][1], f[i][j][1][0]=f[i-1][j][1][1];
        if(j)f[i][j][0][1]=f[i][j-1][0][0]+f[i][j-1][0][1], f[i][j][1][1]=f[i][j-1][1][0]+f[i][j-1][1][1];
    }
}
int main()
{
    ll N, kase=0, a, b, ans;
    init();
    while(scanf("%lld",&N),N)
    {
        if(N<4 or N&1)ans=0;
        else a=N/2-2, b=N/2+2, ans=f[a][b][0][1]+f[a][b][1][0]+f[a][b][1][1];
        printf("Case %lld: %lld\n", ++kase, ans);
    }
    return 0;
}

代码2

//数学题 
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll N;
int main()
{
    ll N, kase=0, a, b, ans, n;
    while(scanf("%lld",&N),N)
    {
        if(N<4 or N&1)ans=0;
        else n=N/2+1, ans=n*(n-1)*(n-2)*(n-3)/12+n*(n-1)*(n-2)/6;
        printf("Case %lld: %lld\n",++kase,ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值