题目
1.出栈序列统计
**********************************************************************源程序名: stack.???(C,CPP) *
*可执行文件名: stack.exe *
*输入文件名: stack.in *
*输出文件名: stack.out *
*********************************************************************
【问题描述】
栈是常用的一种数据结构,有N个元素在栈顶端一侧等待进栈,栈顶端另一侧是出栈序列。你已经知道栈的操作有两种:push和pop,前者是将一个元素进栈,后者是将栈顶元素弹出。现在要使用这两种操作,由一系列操作序列可以得到一系列的输出序列。请你编程求出对于给定的N,计算并输出由等待进栈的序列1,2,……,N,经过一系列操作可能得到的输出序列总数。
【输入】
一个整数N(1<=n<=15)。
【输出】
一个整数,即可能输出序列的总数目。
【样例】
stack.in
3
stack.out
5
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
#include <algorithm>
#define SWAP(x,y) {(x) = (x)^(y); (y)=(x)^(y); (x)=(x)^(y);}
#define MIN(x,y) (x<y?x:y)
#define INF 1e9
#define MAXN 100
int n, m;
int dfs(int num, int cnt){
if(cnt>=n){
m++; return 1;
}
num++;
dfs(num, cnt+1);
while(num>0){
dfs(num-1, cnt+1);
num--;
}
return 1;
}
int main(){
freopen("stack.in", "r+", stdin);
freopen("stack.out", "w+", stdout):
int i;
cin >> n;
m = 0;
dfs(0,1);
cout << m;
return 0;
}
2.走迷宫
**********************************************************************源程序名: maze.???(C,CPP) *
*可执行文件名: maze.exe *
*输入文件名: maze.in *
*输出文件名: maze.out *
*********************************************************************
【问题描述】
有一个M*N格的迷宫(表示有M行、N列),其中有可走的也有不可走的,如果用1表示可以走,0表示不可以走,文件读入这M*N个数据和起始点、结束点的位置。现在要你编程找出所有可行的道路,要求所走的路中没有重复的点,走时只能是上下左右四个方向。如果一条路都不可行,则输出-1。
【输入】
第一行是两个数M,N(1<m,n<15),接下来是M行N列由1和0组成的数据,最后两行是起始点和结束点的坐标信息。
【输出】
一个整数,即能走通且不重复的道路的总数(没有可走通的道路时输出-1)。
【样例】
maze.in
5 6
1 0 0 1 0 1
1 1 1 1 1 1
0 0 1 1 1 0
1 1 1 1 1 0
1 1 1 0 1 1
1 1
5 6
stack.out
12
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
#include <algorithm>
#define SWAP(x,y) {(x) = (x)^(y); (y)=(x)^(y); (x)=(x)^(y);}
#define MIN(x,y) (x<y?x:y)
#define INF 1e9
#define MAXN 100
int m, n;
int ans = 0;
int a[16][16];
int ex, ey;
int dx[] = {0,1,0,-1};
int dy[] = {1,0,-1,0};
bool dfs(int x,int y){
int i;
if(x == ex&&y == ey){
ans++;
return true;
}
for(i=0; i<4; ++i){
int tx = x+dx[i];
int ty = y+dy[i];
if(tx<=0||tx>m||ty<=0||ty>n) return false;
if(a[tx][ty] == 1){
a[tx][ty] = 0;
dfs(tx,ty);
a[tx][ty] = 1;
}
}
return false;
}
int main(){
int i,j;
int sx,sy;
memset(a, 0 ,sizeof(a));
scanf("%d%d", &m, &n);
for(i=1; i<=m; ++i){
for(j=1; j<=n; ++j){
scanf("%d", &a[i][j]);
}
}
scanf("%d%d", &sx, &sy);
scanf("%d%d", &ex, &ey);
ans = 0;
dfs(sx,sy);
printf("%d\n", ans);
return 0;
}
3.组合的输出
**********************************************************************源程序名: compages.???(C,CPP) *
*可执行文件名: compages.exe *
*输入文件名: compages.in *
*输出文件名: compages.out *
*********************************************************************
【问题描述】
排列与组合是常用的数学方法,其中组合就是从N个元素中抽出R个元素(不分顺序且R<=N),我们可以简单地将N个元素理解为1,2,…,N,从中任取R个数。
例如N=5,R=3,所有组合为:
1 2 3 1 2 4 1 2 5 1 3 4 1 3 5 1 4 5 2 3 4 2 3 5 2 4 5 3 4 5
【输入】
一行两个自然数N,R(1<N<21,1<=R<=N)。
【输出】
所有的组合,每一个组合占一行且其中的元素按由小到大的顺序排列,每个元素用一个空格隔开且行尾没有空格,所有的组合也按字典顺序。
【样例】
compages.in
5 3
compages.out
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
#include <algorithm>
#define SWAP(x,y) {(x) = (x)^(y); (y)=(x)^(y); (x)=(x)^(y);}
#define MIN(x,y) (x<y?x:y)
#define INF 1e9
#define MAXN 20
int n,r;
int a[MAXN+5];
int dfs(int now, int len){
if(len == r+1){
for(int i =1; i<=r; ++i)
printf("%d ", a[i]);
printf("\n");
}
if(len>n) return 1;
for(int i=now; i<=n; ++i){
a[len] = i;
dfs(i+1, len+1);
}
}
int main(){
int i,j;
scanf("%d%d", &n, &r);
dfs(1,1);
return 0;
}
4.关路灯
**********************************************************************源程序名: power.???(C,CPP) *
*可执行文件名: power.exe *
*输入文件名: power.in *
*输出文件名: power.out *
*********************************************************************
【问题描述】
某个村庄在一条路线上安装了N盏路灯,每盏灯的功率有大有小(即同一段时间内消耗的电量有多有少)。老张就住在这条路中间某一个路灯旁,他有一项工作就是每天早上天亮时一盏一盏地关掉这些路灯。
为了给村里节省电费,老张记录下了每盏路灯的位置和功率,他每次关灯时也都是尽快地去关,但是老张不知道怎样去关灯才能最省电。他每天都是在天亮时首先关掉自己所在处位置的路灯,然后可以向左向右去关灯。开始他以为先算一下左边路灯的总功率再算一下右边路灯的总功率,然后选择先关掉功率大的一边,再回过头来关掉另一边的路灯,而事实并非如此,因为在关的过程中适当地掉头有可能会更省一些。
现在已知老张走的速度为1m/s,每个路灯的位置(是一个整数,即距路线起点的距离,单位:m)、功率(W),老张关灯所用的时间很短可以忽略不计。
请你为老张编一个程序来安排关灯的顺序,使从老张开始关灯时刻算起所有灯消耗电最少(灯关掉后便不再消耗电了)。
【输入】
文件第一行是两个数字N(0<N<50,表示路灯的总数)和C(1<=C<=N 老张所处位置的路灯号);
接下来N行,每行两个数据,表示第一盏灯到第N栈灯的位置和功率。
【输出】
一个数据,即最少的功耗(单位:J,1J = 1W·S)。
【样例】
power.in
5 3
2 10
3 20
5 20
6 30
8 10
power.out
270 {此时关灯顺序为3 4 2 1 5,不必输出这个关灯顺序}
代码:
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;
#define INF 1e9
#define MIN(x,y) (x<y?x:y)
struct Tnode{
int pos,w;
}node[55];
int ans;
int n;
void dfs(int left, int right, int now, int len, int power, int step){
//printf("len:%d(step:%d),left:%d right:%d now:%d power:%d\n", len, step, left, right, now, power);
if(len == n){
if(ans > power)
ans = power;
//printf("\n");
return ;
}
if(left>0){
int stepk = (step+node[now].pos-node[left].pos);
int powerk = power + stepk*node[left].w;
dfs(left-1, right, left, len+1, powerk, stepk);
}
if(right<=n){
int stepk = step + node[right].pos - node[now].pos;
int powerk = power + stepk*node[right].w;
dfs(left, right+1, right, len+1, powerk, stepk);
}
}
int main(){
int c;
scanf("%d%d", &n, &c);
for(int i=1; i<=n; ++i){
scanf("%d%d", &node[i].pos, &node[i].w);
}
ans = INF;
dfs(c-1, c+1, c, 1, 0, 0);
printf("%d\n", ans);
return 0;
}