两道NOI题目

wenxinfly 2003-12-12 06:44:02
1。有n面红旗和n面黄旗从东到西插成一排。如果相邻的两面旗帜的颜色不同,则称为颜色发生一次改变。

任务:计算这2n面旗帜的颜色改变m次的插法共有多少种?

输入:从键盘上依闪输入自然数n和m。(n<15)

输出:把插法总数在屏幕上显示输出。

2。4X4的方格棋盘上有一颗骰子(骰子的尺寸与方格大小一致)放在位置“+”,该骰子从“+”出发,每次只允许向左或者向下翻动一下,骰子的立体图和各面展开图表达了骰子各面的数字分布情况。设骰子的顶面的数字为p,N方向的那一面的数字为q,则用(p,q)表示骰子当时的状态。例如,图中所示的骰子的状态表示为(1,5)。

任务:根据输入的状态,求出要翻动多少次才能使骰子到达“-”位置,并且使其在“-”位置时的 (p^2)*(q^3)尽可能大。

输入:从键盘上输入骰子的初始状态(两个自然数)。

输出:输出每一次翻动后的状态(p,q)和对应的(p^2)*(q^3)值。









...全文
64 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhushizu 2003-12-12
  • 打赏
  • 举报
回复
强,强!
wenxinfly 2003-12-12
  • 打赏
  • 举报
回复
很感谢 gushaoping(五月)
gushaoping 2003-12-12
  • 打赏
  • 举报
回复


以上可完全运行.
gushaoping 2003-12-12
  • 打赏
  • 举报
回复
#include<iostream.h>
#include<stdlib.h>
#include<stdio.h>
#define maxqsize 50
#define error 0
int count=0;
class result
{
private:
int **data;
int head;
int rear;
int length;
public:
result()
{
data=(int**)malloc(sizeof(int*)*maxqsize);
head=0;
rear=0;
length=0;
}
void copytf(FILE *fp)
{
int count=1,temp=0;
int current=head;
if (isempty())
return;
while(current!=rear)
{
int *b=data[current];
fprintf(fp,"%d ",count);
count++;
for (int i=1;i<=b[0];i++)
{
temp=b[i];
do
{
if (i%2)
fprintf(fp,"%c",'1');
else
fprintf(fp,"%c",'0');
temp--;
}while(temp>0);
}//for
fprintf(fp,"\n");
current=(current+1)%maxqsize;
}//while current
}

int isempty()
{
if (head==rear)
return 1;
else
return 0;
}

void output()
{
int temp=head;
while(temp!=rear)
{
for (int j=1;j<=data[temp][0];j++)
cout<<data[temp][j];
cout<<endl;
temp=(temp+1)%maxqsize;
}
cout<<length<<"项";
}

int pop(int a[])
{
if (head==rear)
return error;
a[0]=data[head][0];
for (int j=1;j<=a[0];j++)
a[j]=data[head][j];
head=(head+1)%maxqsize;
length--;
return 0;
}

int push(int a[])
{
if( (rear+1)%maxqsize==head)
return error;
data[rear]=new int(a[0]+1);
for (int i=0;i<=a[0];i++)
data[rear][i]=a[i];
rear=(rear+1)%maxqsize;
length++;
return 1;
}
};

gushaoping 2003-12-12
  • 打赏
  • 举报
回复

以下的0,1当作红旗与黄旗,
把固定的参数改一下就可以了。


#include "ma.h"

static int sum,segment,maxsize;
int a[maxsize];
result q;

int account(int,int);
bool bc(int num,int seg,int size);
int makemin(int,int,int,int);
void outputarray(int a[],int);

void main()
{
//根据给定的s,k,m求出满足规则的条形码的集合
// s是条形码的长度,k是条形码的段数(连续的1或0为一段)
// m是一段条形码最大宽度。
FILE *fp=NULL;
char *s=new char[10]; // 结果文件
cout<<"input the sum,segment,maxsize";
cin>>sum>>segment>>maxsize;
cout<<"input the file to save";
cin>>s;
fp=fopen(s,"w");
if (bc(sum,segment,maxsize)) //输入合法则结果保存到文件
if (q.isempty()) //有条形编码
{
q.copytf(fp);
cout<<"the file has stored"<<endl;
}
else
cout<<"the result is empty"; //没有一个条形编码
else
cout<<"the data is illegal"; //输入不合法
}

void outputarray(int a[],int n)
{
int i=0;
while(i<n)
{
cout<<a[i];
i++;
}
}

int makemin(int startsg,int endsg,int size,int num)
{
//产生 num个0,1组成的二进制数,这个二进制数是满足一定规则的最小数
//规则是:
// 必须包含 endsg-startsg+1 段,这里的一段是指连续的一串1或
//连续的一串0 ,段的最大长度不超过给定的 size
if (startsg>endsg||startsg<1||endsg>segment)//段值小于1或大于最大段则不合法
return false;
int seg=endsg-startsg+1;
if (num<seg||num>seg*size)// 分不下或不够分
return false;
int i=0;
if (seg==1) {a[startsg]=num;return true;}//只有一段则直接分配

for(i=startsg;i<=endsg;i++) a[i]=1;//每段不能为空
int num1=num-seg; //剩下要分配的0,1数目
int intseg=num1/(size-1);//够分的整段数
int remain=num1%(size-1);//余下不够一段

int evensg,j;
int firstevensg=startsg%2+startsg;//第一个奇数段号
int lastoddsg=endsg-(!(endsg%2));//最后一个偶数段号
if (seg%2==1&&startsg%2==0)//统计偶数段数
evensg=seg/2+1;
else
evensg=seg/2;
i=firstevensg;j=intseg;
while(i<=endsg&&j>0) //偶数段从高到低(对应值为0),
{ //奇数段从低到高(对应值为1)
a[i]=size; //确保得到最小值
j--;i+=2;
}//while
if (evensg<=intseg)
{
i=lastoddsg;j=intseg-evensg;
while(i>=startsg&&j>0)
{
a[i]=size;j--;i-=2;
}
}//if
a[i]+=remain;return true;
}

bool bc(int num,int seg,int size)
{
if (num<seg||num>seg*size)
return error;
a[0]=seg;
int endsg=seg;
int i=endsg-(!(endsg%2));//每段长度为size
makemin(1,endsg,size,num);//调整为最小
q.push(a);
while(i>0)
{
if(a[i]<size)//本段未达最值,且可向右扩充便扩充继续循环否则考虑下面的进位
if(makemin(i+1,endsg,size,account(i+1,endsg)-1))
{
a[i]++;
q.push(a);
i=endsg-(!(endsg%2));//指向最后一奇数段
continue;
}
if (i>1&&a[i-1]>1&&makemin(i,endsg,size,account(i,endsg)+1))
{
a[i-1]--;//位置不过多且不过少且前一段充许则使前一段长减1并重新排以右的段
q.push(a);
i=endsg-(!(endsg%2));
}
else
i-=2; //否则前一个奇数段成为当前段
}//while
return 1;
}//bc

int account(int ss,int es)
{
if (ss>es)
return 0;
int sum=0;
for (int i=ss;i<=es;i++)
sum+=a[i];
return sum;
}
wenxinfly 2003-12-12
  • 打赏
  • 举报
回复
有谁帮讲讲
016liuzhi@sohu.com

33,028

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧