NOIP 提高组 初赛 四、阅读程序写结果 习题集(七)NOIP2010-NOIP2011
NOIP 提高组 初赛 四、阅读程序写结果 习题集(七)NOIP2010-NOIP2011
1.第十六届(NOIP2010)
问题:
1.
//2010.4.1
#include <stdio.h>
#define size 10
int main(){
int i,j,cnt,n,m;
int data[size];
scanf("%d%d\n",&n,&m);
for(i=1;i<=n;i++)
scanf("%d",&data[i]);
for(i=1;i<=n;i++){
cnt=0;
for(j=1;j<=n;j++)
if(data[i]<data[j]||(data[j]==data[i]&&j<i))
cnt++;
if(cnt==m)
printf("%d\n",data[i]);
}
return 0;
}
//输入:
//5 2
//96 -8 0 16 87
2.
//2010.4.2
#include <stdio.h>
#define size 100
int main(){
int na,nb,i,j,k;
int a[size],b[size];
scanf("%d\n",&na);
for(i=1;i<=na;i++)
scanf("%d",&a[i]);
scanf("%d\n",&nb);
for(i=1;i<=nb;i++)
scanf("%d",&b[i]);
i=1;
j=1;
while(i<=na&&j<=nb){
if(a[i]<=b[j]){
printf("%d ",a[i]);
i++;
}else{
printf("%d ",b[j]);
j++;
}
}
if(i<=na)
for(k=i;k<=na;k++)
printf("%d ",a[k]);
if(j<=nb)
for(k=j;k<=nb;k++)
printf("%d ",b[k]);
return 0;
}
//输入:
//5
//1 3 5 7 9
//4
//2 6 10 14
3.
//2010.4.3
#include <stdio.h>
#define num 5
int r(int n){
int i;
if(n<=num)
return n;
for(i=1;i<=num;i++)
if(r(n-i)<0)
return i;
return -1;
}
int main(){
int n;
scanf("%d",&n);
printf("%d\n",r(n));
return 0;
}
//输入:16
4.
//2010.4.4
#include <stdio.h>
#include <string.h>
#define size 100
int n,m;
int r[size];
int map[size][size];
int find;
int successful(){
int i;
for(i=1;i<=n;i++)
if(map[r[i]][r[i%n+1]]==0)
return 0;
return 1;
}
void swap(int *a,int *b){//此处网络流传的pascal写法应该是有问题的
int t;
t=*a;
*a=*b;
*b=t;
}
void perm(int left,int right){
int i;
if(find==1)
return;
if(left>right){
if(successful()==1){
for(i=1;i<=n;i++)
printf("%d ",r[i]);
find=1;
}
return;
}
for(i=left;i<=right;i++){
swap(r+left,r+i);
perm(left+1,right);
swap(r+left,r+i);
}
}
int main(){
int x,y,i;
scanf("%d%d",&n,&m);
memset(map,0,sizeof(map));
for(i=1;i<=m;i++){
scanf("%d%d",&x,&y);
map[x][y]=1;
map[y][x]=1;
}
for(i=1;i<=n;i++)
r[i]=i;
find=0;
perm(1,n);
if(find==0)
printf("No solution\n");
return 0;
}
//输入:
/*
9 12
1 2
2 3
3 4
4 5
5 6
6 1
1 7
2 7
3 8
4 8
5 9
6 9
*/
问题解答:
1.读程序,并试着执行,很快能发现,是在5个输入数据中找到第三大的数,
很快得出答案:16
1简单
2.顺着程序执行,很快就能得到答案,思考过程如图所示:
答案:1 2 3 5 6 7 9 10 14
2简单
3.该题是自下而上练习递归的好题。
从r(16)开始执行此题很难,自下而上开始执行,此题比较简单。
出答案分分钟的事。思考过程如图所示:
答案:4
3简单
4.此题模拟了
perm(1,1)打印No solution
perm(1,2)打印1 2
perm(1,3)打印No solution
没发现什么规律,暂放弃。
答案:1 6 9 5 4 8 3 2 7
来自http://blog.sina.com.cn/s/blog_8c35725a0100xddr.html
④ 求哈密尔顿回路
这题的关键是看懂successful函数的含义。搜索的过程并不难看懂,如果实在看不懂手动模拟一下也能看出来是一个对于r[n]方案的枚举,successful是判断r[n]里储存的方案是否是一个合法的哈密尔顿回路。当然这题一个非常非常易错的地方就是搜索的顺序决定了输出的方案必定是所有可行方案的字典序最小的一个,尽管输入数据只有两组方案,但是由于输入数据给定的顺序问题,也有许多同学忽略了这个问题,造成不必要的失分。
2016-12-27
1.第十七届(NOIP2011)
问题:
1.
//2011.4.1
#include <stdio.h>
#include <string.h>
#define size 100
int main(){
int n,i,sum,x;
int a[size];
scanf("%d",&n);
memset(a,0,sizeof(a));
for(i=1;i<=n;i++){
scanf("%d",&x);
a[x]++;
}
i=0;
sum=0;
while(sum<(n/2+1)){
i++;
sum+=a[i];
}
printf("%d\n",i);
return 0;
}
//输入:11
//4 5 6 6 4 3 3 2 3 2 1
2.
//2011.4.2
#include <stdio.h>
int n;
void f2(int x,int y);
void f1(int x,int y){
if(x<n)
f2(y,x+y);
}
void f2(int x,int y){
printf("%d ",x);
f1(y,x+y);
}
int main(){
scanf("%d",&n);
f1(0,1);
return 0;
}
//输入:30
3.
//2011.4.3
#include <stdio.h>
#define v 100
int visited[v];
int e[v][v];
int n,m,ans;
void dfs(int x,int len){
int i;
visited[x]=1;
if(len>ans)
ans=len;
for(i=1;i<=n;i++)
if(visited[i]==0&&e[x][i]!=-1)
dfs(i,len+e[x][i]);
visited[x]=0;
}
int main(){
int i,j,a,b,c;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
e[i][j]=-1;
for(i=1;i<=m;i++){
scanf("%d%d%d",&a,&b,&c);
e[a][b]=c;
e[b][a]=c;
}
for(i=1;i<=n;i++)
visited[i]=0;
ans=0;
for(i=1;i<=n;i++)
dfs(i,0);
printf("%d\n",ans);
return 0;
}
//输入:
/*
4 6
1 2 10
2 3 20
3 4 30
4 1 40
1 3 50
2 4 60
*/
4.
//2011.4.4
#include <stdio.h>
#include <string.h>
#define size 10000
#define length 10
int n,m;
int a[size][length];
int h(int u,int v){
int ans,i;
ans=0;
for(i=1;i<=n;i++)
if(a[u][i]!=a[v][i])
ans++;
return ans;
}
int main(){
int sum,i,j;
scanf("%d",&n);
memset(a,0,sizeof(a));
m=1;
while(1){
i=1;
while(i<=n&&a[m][i]==1)
i++;
if(i>n)
break;
m++;
a[m][i]=1;
for(j=i+1;j<=n;j++)
a[m][j]=a[m-1][j];
}
sum=0;
for(i=1;i<=m;i++)
for(j=1;j<=m;j++)
sum+=h(i,j);
printf("%d\n",sum);
return 0;
}
//输入:7
问题解答:
1.该题比较简单,顺着程序执行,思考过程如图所示:
答案:3
1简单
2.该题比较简单,该题也是练递归的好题,顺着程序执行,思考过程如图所示:
答案:1 2 5 13 34
2简单
3.思考过程如图所示,试着跟踪程序一个分支到底,试图弄明白程序意图。
该程序遍历所有的点,不能重复,找出最大长度。即一笔画,找出最大长度。思考过程如图所示:
答案:60+40+50=150
3中等
4.思考过程如图所示:
费了好大劲,才弄明白,程序是模拟二进制加法,每次加1。
最终m=128.
接下来,再也无力处理sum部分,如果是考试,此时只能放弃了。
参考http://wenku.baidu.com/link?url=j_VjatBanHeEfnRpqHD6b_eJo0vK8BR5ddr3CKpQ7YfEUpqhdqEO3Ecl41GPDf4X3qhSBkKbM9AvWfAGAAmhc8cqAleYxjr3C5fEP3ejD67
不过没看懂,不过坚定了能做出的信心,后细细思考,得出答案,将过程表述如下。
每列有128个数,其中64个0,64个1。
故每列中任取一个数,与其它127个数不同的计数有64个。
一共有7列,计数64*7
共128行,计数64*7*128=57344
答案:57344
4难
2016-12-28