C语言 假设n个竞赛者排成一个环形,依次顺序编号1,2,…,n。从某个指定的第1号开始,沿环计数,每数到第m

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言 假设n个竞赛者排成一个环形,依次顺序编号1,2,…,n。从某个指定的第1号开始,沿环计数,每数到第m相关的知识,希望对你有一定的参考价值。

数到m个人就出列 剩下的重新报数 以此类推 直到所有人都出列 有一个这样的程序
#include <stdio.h>
#include <stdlib.h>

typedef struct node
int data;
struct node *next;
Lnode;
//线性表单链表存储结构,见课本P28

Lnode * create (int n)
int i;
Lnode *h,*p,*r=(Lnode*)malloc(sizeof(Lnode));
r->data=n;
h=r;
for (i=n-1;i>0;i--)
p=(Lnode*)malloc(sizeof(Lnode));
p->data=i;
p->next=h;
h=p;

r->next=h;
return h;

//用前插法建立单循环链表,参考课文P30和P35

void jeseph(Lnode *p,int m)
Lnode *q; int j=0;
printf("outqueue order:\n");
do
j++;
if(j==m-1)
q=p->next;
p->next=q->next;//删除q结点
printf("%d ",q->data);//将q结点的数据输出
j=0;free(q);

p=p->next;//指针后移

while (p->next !=p);//循环直到剩余最后一个结点
printf("%d\n",p->data);
free(p);


void main ()
Lnode *h;
int m,n;
printf("Please input n,m=");
scanf("%d,%d",&n,&m);
h=create(n);
jeseph(h,m);

但是当m=1时不能输出,请问错在哪里?要怎么改??

void jeseph(Lnode *p,int m)

Lnode *q; int j=0;
printf("outqueue order:\\n");
while (p->next !=p) //不要用do while,直接使用while就好了

j++;
if(j==m-1)

q=p->next;
p->next=q->next;//删除q结点
printf("%d ",q->data);//将q结点的数据输出
j=0;free(q);

p=p->next;//指针后移

printf("%d\\n",p->data);
free(p);
追问

m=1还是不能输出。。

追答

你输入的是什么? 如何输入的?能不能将你的测试粘出来,我测试过了,没有问题啊!
如:
Please input n,m= 1,2
outqueue order:
1
Please input n,m=5,2
outqueue order:
2 4 1 5 3

参考技术A 建议加一个头结点!这样比较容易实现操作的统一性!
在main函数中加一个头结点就是! 你自己改一下或许就解决了!追问

能直接八要加的发过来么- -。。。。。整不好。

追答

不加?这个何必呢...加一个再去掉,最多!这个是顶省事的了.要么搞个循环链表形式的也不错.

参考技术B 错误在于if(j == m-1);处,将dowhile()循环该为for();循环,既改为:for ( ; p->next !=p; j++)。追问

有这个

追答

这样修改:
void jeseph(Lnode *p,int m)

Lnode *q;
int j=0;
printf("outqueue order:\n");
for ( ; p->next != p; j++)

if(j == m-1)

q=p->next;
p->next=q->next;//删除q结点
printf("%d ",q->data);//将q结点的数据输出
j=0;
free(q);

p=p->next;//指针后移

printf("%d\n",p->data);
free(p);

我的编译error与warning都没有。

追问

有执行过没 程序倒是没有错 不过结果好像有点问题。。。。

NOIP2009pj道路游戏[环形DP 转移优化 二维信息]

题目描述

小新正在玩一个简单的电脑游戏。

  游戏中有一条环形马路,马路上有 n 个机器人工厂,两个相邻机器人工厂之间由一小段马路连接。小新以某个机器人工厂为起点,按顺时针顺序依次将这 n 个机器人工厂编号为1~n,因为马路是环形的,所以第 n 个机器人工厂和第 1 个机器人工厂是由一段马路连接在一起的。小新将连接机器人工厂的这 n 段马路也编号为 1~n,并规定第 i 段马路连接第 i 个机器人工厂和第 i+1 个机器人工厂(1≤i≤n-1),第 n 段马路连接第 n 个机器人工厂和第 1个机器人工厂。   游戏过程中,每个单位时间内,每段马路上都会出现一些金币,金币的数量会随着时间发生变化,即不同单位时间内同一段马路上出现的金币数量可能是不同的。小新需要机器人的帮助才能收集到马路上的金币。所需的机器人必须在机器人工厂用一些金币来购买,机器人一旦被购买,便会沿着环形马路按顺时针方向一直行走,在每个单位时间内行走一次,即从当前所在的机器人工厂到达相邻的下一个机器人工厂,并将经过的马路上的所有金币收集给小新,例如,小新在 i(1≤i≤n)号机器人工厂购买了一个机器人,这个机器人会从 i 号机器人工厂开始,顺时针在马路上行走,第一次行走会经过 i 号马路,到达 i+1 号机器人工厂(如果 i=n,机器人会到达第 1 个机器人工厂),并将 i 号马路上的所有金币收集给小新。 游戏中,环形马路上不能同时存在 2 个或者 2 个以上的机器人,并且每个机器人最多能够在环形马路上行走 p 次。小新购买机器人的同时,需要给这个机器人设定行走次数,行走次数可以为 1~p 之间的任意整数。当马路上的机器人行走完规定的次数之后会自动消失,小新必须立刻在任意一个机器人工厂中购买一个新的机器人,并给新的机器人设定新的行走次数。 以下是游戏的一些补充说明:

  1. 游戏从小新第一次购买机器人开始计时。

  2. 购买机器人和设定机器人的行走次数是瞬间完成的,不需要花费时间。
  3. 购买机器人和机器人行走是两个独立的过程,机器人行走时不能购买机器人,购买完机器人并且设定机器人行走次数之后机器人才能行走。
  4. 在同一个机器人工厂购买机器人的花费是相同的,但是在不同机器人工厂购买机器人的花费不一定相同。
  5. 购买机器人花费的金币,在游戏结束时再从小新收集的金币中扣除,所以在游戏过程中小新不用担心因金币不足,无法购买机器人而导致游戏无法进行。也因为如此,游戏结束后,收集的金币数量可能为负。 现在已知每段马路上每个单位时间内出现的金币数量和在每个机器人工厂购买机器人需要的花费,请你告诉小新,经过 m 个单位时间后,扣除购买机器人的花费,小新最多能收集到多少金币。

输入输出格式

输入格式:

第一行 3 个正整数,n,m,p,意义如题目所述。

接下来的 n 行,每行有 m 个正整数,每两个整数之间用一个空格隔开,其中第 i 行描 述了 i 号马路上每个单位时间内出现的金币数量(1≤金币数量≤100),即第 i 行的第 j(1≤j≤m)个数表示第 j 个单位时间内 i 号马路上出现的金币数量。

最后一行,有 n 个整数,每两个整数之间用一个空格隔开,其中第 i 个数表示在 i 号机器人工厂购买机器人需要花费的金币数量(1≤金币数量≤100)。

输出格式:

共一行,包含 1 个整数,表示在 m 个单位时间内,扣除购买机器人 花费的金币之后,小新最多能收集到多少金币。

输入输出样例

输入样例#1:
2 3 2 
1 2 3 
2 3 4 
1 2
输出样例#1:
5

说明

【数据范围】

对于 40%的数据,2≤n≤40,1≤m≤40。

对于 90%的数据,2≤n≤200,1≤m≤200。

对于 100%的数据,2≤n≤1000,1≤m≤1000,1≤p≤m。

NOIP 2009 普及组 第四题

------------------------------------------------------------------

一些节点组成一个环,相邻节点的道路上不同时间权值不同,机器人要花费,求最多金币

---------------------------------------------------------------------------

几个月前被虐,现在还凑合

f[i][j]表示i个时间到了节点j的最大金币数

可以枚举上一个机器人的p,维护fmx和价值和,复杂度O(n3)

考虑当前状态,可以由上一个状态走来(一定是p>1最优的),也可以新买一个,保存上一个状态的step,就可以O(1)转移了

有点像二维信息,比如vijos1392

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const int N=1005,INF=1e9;
int read(){
    int x=0,f=1;char ch=getchar();
    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;
}
int n,m,p,coin[N][N],cost[N];
int f[N][N],fmx[N],step[N][N];
inline int pre(int x){
    if(x==1) return n;
    return x-1;
}

void dp(){
    //for(int i=1;i<=n;i++) f[1][n]=coin[]
    //for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) f[i][j]=-INF,fmx[i]=-INF; 
    for(int j=1;j<=n;j++) 
        f[1][j]=coin[1][pre(j)]-cost[pre(j)],step[1][j]=1,fmx[1]=max(fmx[1],f[1][j]);
    for(int i=2;i<=m;i++){
        fmx[i]=-INF;
        for(int j=1;j<=n;j++){
            int pj=pre(j);
            f[i][j]=fmx[i-1]+coin[i][pj]-cost[pj]; 
            step[i][j]=1;
            if(step[i-1][pj]<p&&f[i][j]<f[i-1][pj]+coin[i][pj]) {
                f[i][j]=f[i-1][pj]+coin[i][pj];
                step[i][j]=step[i-1][pj]+1;
            }
            fmx[i]=max(fmx[i],f[i][j]);
        }
    }
}
int main(){
    n=read();m=read();p=read();
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) coin[j][i]=read();
    for(int i=1;i<=n;i++) cost[i]=read();
    dp();
    printf("%d",fmx[m]);
}

 

以上是关于C语言 假设n个竞赛者排成一个环形,依次顺序编号1,2,…,n。从某个指定的第1号开始,沿环计数,每数到第m的主要内容,如果未能解决你的问题,请参考以下文章

C语言编程问题

NOIP2009pj道路游戏[环形DP 转移优化 二维信息]

道路游戏

一群猴子排成一圈,按1 2 3 ... n依次编号

6链表-单向环形链表

Josephu问题与单向环形链表