| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 671 人关注过本帖
标题:算法优化(题目有点长,希望有兴趣的可以看下去)
只看楼主 加入收藏
ab1034982749
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
帖 子:215
专家分:1185
注 册:2012-4-14
结帖率:100%
收藏
已结贴  问题点数:100 回复次数:6 
算法优化(题目有点长,希望有兴趣的可以看下去)
题目如下:
      下学期一共有n次考试,考试科目有4种,分别为理科(物理化学生物)、文科(历史地理艺术)、必修(语文数学英语)和综合。每次考哪一科是不定的,因此在考试前Jace不知道应该去复习哪一科的功课。Jace希望能预测出下一次可能考的科目。于是,Jace收集到了以往的考试的资料。从以往的考试中,他发现了这样几个规律:

      1.如果这次考的是理科,那么下一次一定会考文科;
      2.如果这次考的是综合,那么下一次一定会考必修;
      3.如果这次考的是文科,那么下一次要么考理科,要么考必修;
      4.如果这次考的是必修,那么下一次要么考文科,要么考综合。

    Jace已经知道,本学期的第一次考试科目为理科。他打算拟定一个可以应对所有可能情况的应考复习计划。因此,他想知道,整个学期有多少种可能的考试科目安排满足以上规律。

要求:
输入
一个正整数n,代表本学期总的考试次数。
输出
一个正整数,表示符合规律的科目安排方案的总数。考虑到这个结果可能会很大,因此你只需要输出它mod 7654321的值即可。


测试实例:
输入示例
5
输出示例
5

其他说明:
当n=5时,有以下5种方案满足要求:
理科-->文科-->理科-->文科-->理科
理科-->文科-->理科-->文科-->必修
理科-->文科-->必修-->文科-->理科
理科-->文科-->必修-->文科-->必修
理科-->文科-->必修-->综合-->必修
对于50%的数据,1≤n≤10.
对于60%的数据,1≤n≤20.
对于80%的数据,1≤n≤1000.
对于100%的数据,1≤n≤10000.
(没有n=10000这个数据哦)

注意事项:
运行时间限制:1000ms

希望各位大神给与解答:

本人也写了一个程序但是当n>50的时候就基本上要超时间了,
所以希望各位大神帮忙。提高运行效率
我的程序如下:


#include <stdio.h>
#include <stdlib.h>
typedef struct stack
{
    int s;
    struct stack * next[2];

} Stack,* PStack;

struct exam {
    int x;
    int y;
};
PStack data[4];
int n;
long total=0;
struct exam a[10000];
void run(int k);
int main(void)
{
    int i,j;
    for (i=0;i<4;i++){
        data[i]=(PStack)malloc(sizeof(Stack));
        data[i]->s=i;
    }
    data[0]->next[0]=data[1];
    data[0]->next[1]=NULL;
    data[1]->next[0]=data[0];
    data[1]->next[1]=data[2];
    data[2]->next[0]=data[1];
    data[2]->next[1]=data[3];
    data[3]->next[0]=data[3];
    data[3]->next[1]=NULL;
    total=0;
    a[0].x=0;
    a[1].x=1;
    scanf("%d",&n);

    if (n<=2) {
        total=1;
        printf("%d\n",total);
        return 0;
    }

    for (i=2;i<n;i++){

        a[i].x=data[a[i-1].x]->next[0]->s;

    }
    total++;

    i=n-2;
    while(i>=1)
    {
        if (data[a[i].x]->next[1] == NULL || a[i].y==1)
        {
            i--;
        }
        else
        {
            a[i].y=1;
            for (j=i+1;j<n;j++)
            {
                    a[j].x=data[a[j-1].x]->next[a[j-1].y]->s;
                    a[j].y=0;
            }
            total++;
            i=n-2;
        }

    }
    printf("%ld\n",total%7654321);
    return 0;

   
}
搜索更多相关主题的帖子: 考试科目 
2013-05-14 13:21
czz5242199
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:4
帖 子:660
专家分:2400
注 册:2011-10-26
收藏
得分:80 
程序代码:
#include <iostream>
#define M 7654321
using namespace std;

int f[10000][4],n;

int main()
{   
    cin>>n;
    f[0][0]=1;
    for (int i=1; i<n; i++)
    {
        f[i][0]=f[i-1][2];
        f[i][1]=f[i-1][3];
        f[i][2]=(f[i-1][0]+f[i-1][3])%M;
        f[i][3]=(f[i-1][1]+f[i-1][2])%M;
    }
    cout<<(f[n-1][0]+f[n-1][1]+f[n-1][2]+f[n-1][3])%M<<endl;
}
    
    
2013-05-14 13:28
azzbcc
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:江西财经大学
等 级:贵宾
威 望:81
帖 子:3293
专家分:12919
注 册:2012-11-4
收藏
得分:0 
确实是递推,分给曹哥就好,楼主想复杂了吧


[fly]存在即是合理[/fly]
2013-05-14 13:45
hahayezhe
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖南张家界
等 级:贵宾
威 望:24
帖 子:1386
专家分:6999
注 册:2010-3-8
收藏
得分:0 
1,1,2,3,5,8 ,13......排列组合

于是此题可以得出一个规律
设第n个时,文科和必修为x ,理科和综合为 Y, 
则有 a(n) = 2*x + y 种可能,

这时我们再来看 x和y有什么关系呢。

发现 单(理科和综合只能得出一个为单)下一个必为双(文和必修都是两个),双必为一个单,一个双,
于是又有 x(n) = x(n-1)+y(n-1)
          y(n) = x(n-1)

规律出来了 效率也就出来了-- 代码自己写 分给我吧。
2013-05-14 14:13
hahayezhe
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖南张家界
等 级:贵宾
威 望:24
帖 子:1386
专家分:6999
注 册:2010-3-8
收藏
得分:20 
附上图解:

n:  x:  y:
1   0   1
2   1   0
3   1   1
4   2   1
5   3   2
6   5   3
7   8   5
....
2013-05-14 14:20
hahayezhe
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖南张家界
等 级:贵宾
威 望:24
帖 子:1386
专家分:6999
注 册:2010-3-8
收藏
得分:0 
还没有出来吗?

在提示下

x和y满足排列组合 
a(n) = a(n-1) + a(n-2)
a(n-1) = a(n-2) + a(n-3)
....代入  于是得到什么公式呢??? 自己动脑!!!!!!!
2013-05-14 14:31
hahayezhe
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖南张家界
等 级:贵宾
威 望:24
帖 子:1386
专家分:6999
注 册:2010-3-8
收藏
得分:0 
程序代码:
#include <Windows.h>
#include <math.h>
double g_Num = sqrt(5.0);
double FisNum(const int n)
{
    return (pow((1.0+g_Num)/2.0,n) - pow((1.0 - g_Num)/2.0,n))/g_Num;
}
int _tmain(int argc, _TCHAR* argv[])
{
    int n;
    scanf("%d",&n);
    DWORD _time = GetTickCount();
    printf("%g\n",FisNum(n-1) + FisNum(n-2));
    printf("time=%d",GetTickCount()-_time);
    return 0;
}
2013-05-14 15:13
快速回复:算法优化(题目有点长,希望有兴趣的可以看下去)
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.026939 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved