1.
题目背景
给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过。给定起点坐标和终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案。在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。
题目描述
无
输入格式
第一行N、M和T,N为行,M为列,T为障碍总数。第二行起点坐标SX,SY,终点坐标FX,FY。接下来T行,每行为障碍点的坐标。
输出格式
给定起点坐标和终点坐标,问每个方格最多经过1次,从起点坐标到终点坐标的方案总数。
输入输出样例
输入 #1
2 2 1 1 1 2 2 1 2输出 #1复制
1说明/提示
【数据规模】
1≤N,M≤5
#include<stdio.h>
int n,m,t,sum=0;//N为行,M为列,T为障碍总数
int sx,sy,fx,fy,cx,cy;//起点坐标SX,SY,终点坐标FX,FY, 障碍坐标CX,CY
int a[6][6],book[6][6];
void dfs(int x,int y)
{
int next[4][2]={{0,1},//向右
{1,0},//向下
{0,-1},//向左
{-1,0}};//向上
if(x == fx&&y == fy)//到达终点
{
sum++;
return;
}
int tx,ty,k;
//枚举四种走法
for(k=0;k<4;k++)
{
tx=x+next[k][0];
ty=y+next[k][1];
if(tx<1||ty<1||tx>n||ty>m)
continue;
if(a[tx][ty] == 0&&book[tx][ty] == 0)
{
book[tx][ty]=1;
dfs(tx,ty);
book[tx][ty]=0;
}
}
return ;
}
int main()
{
scanf("%d %d %d",&n,&m,&t);
scanf("%d %d %d %d",&sx,&sy,&fx,&fy);
int k=0;
while(t--)
{
scanf("%d %d",&cx,&cy);
a[cx][cy]=1;//标记障碍处
}
book[sx][sy]=1;//标记起点已经在路径中
dfs(sx,sy);
printf("%d",sum);
return 0;
}
2.
题目描述
一个如下的 6 \times 66×6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。
上面的布局可以用序列 2\ 4\ 6\ 1\ 3\ 52 4 6 1 3 5 来描述,第 ii 个数字表示在第 ii 行的相应位置有一个棋子,如下:
行号 1\ 2\ 3\ 4\ 5\ 61 2 3 4 5 6
列号 2\ 4\ 6\ 1\ 3\ 52 4 6 1 3 5
这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
并把它们以上面的序列方法输出,解按字典顺序排列。
请输出前 33 个解。最后一行是解的总个数。输入格式
一行一个正整数 nn,表示棋盘是 n \times nn×n 大小的。
输出格式
前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。
输入输出样例
输入 #1复制
6输出 #1复制
2 4 6 1 3 5 3 6 2 5 1 4 4 1 5 2 6 3 4说明/提示
【数据范围】
对于 100\%100% 的数据,6 \le n \le 136≤n≤13。题目翻译来自NOCOW。
USACO Training Section 1.5
#include<stdio.h>
int n,sum=0;//全局变量未初始化时默认为0
///不能全局定义col(开始被这个错误卡了好久)
int a[100],b[100],c[100],d[100];
///之所以不设置为13是因为对角线数远大于N,干脆都开大一些
void dfs(int row)
{
if(row==n+1)//如果遍历到了第n+1行,则说明已经出了一组结果
{
if(sum<3)
{
for(int g=1; g<=n; g++)
{
printf("%d ",a[g]);
}
printf("\n");
}
sum++;
return;
}
for(int col=1; col<=n; col++)//每一行从第一个位置开始遍历尝试
{
if((b[col] == 0)&&(c[row+col] == 0)&&(d[row-col+n] == 0))
{
a[row]=col;//记录皇后位置
b[col]=1;
c[row+col]=1;//这里
d[row-col+n]=1;//和这里 就是标记了当前皇后所在位置的对角线被标记了
//其中\对角线的表示之所以要加个n是yw有些情况row-col为负数,但数组下标不能为负数,所以这里整体右移n个单位使\对角线数组的下标为正
dfs(++row);//进一步搜索!
row--;
///这里不能用row++!!!!!!!
b[col]=0;
c[row+col]=0;
d[row-col+n]=0;//这三行是在回溯
}
}
return;
}
int main()
{
scanf("%d",&n);
dfs(1);
printf("%d",sum);
return 0;
}
3.
题目描述
任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和。现在给你一个自然数n,要求你求出n的拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,其中字典序小的序列需要优先输出。
输入格式
输入:待拆分的自然数n。
输出格式
输出:若干数的加法式子。
输入输出样例
输入 #1复制
7输出 #1复制
1+1+1+1+1+1+1 1+1+1+1+1+2 1+1+1+1+3 1+1+1+2+2 1+1+1+4 1+1+2+3 1+1+5 1+2+2+2 1+2+4 1+3+3 1+6 2+2+3 2+5 3+4说明/提示
用回溯做。。。。
n\le 8n≤8
#include<stdio.h>
int n,l,a[10];//n<=8
void dfs(int sum,int data)//sum表示当前总和,data表示本次调用函数sum需从data加起
{
int i;
if(sum == n)
{
for(i=0;i<l-1;i++)
printf("%d+",a[i]);
printf("%d\n",a[i]);//最后一个数后面没有加号
return;//已经得到一组答案,回溯到上一步
}
if(sum > n)
return;//超过了,不合适,回到上一步
if(sum < n)
{
for(i=data; i<n; i++)//加的数从1开始遍历
{
a[l++]=i;
dfs(sum+i,i);
a[--l]=0;//回溯
}
}
return;
}
int main()
{
scanf("%d",&n);
dfs(0,1);//sum起初是0,从加1开始
return 0;
}
4.
题目描述
Due to recent rains, water has pooled in various places in Farmer John's field, which is represented by a rectangle of N x M (1 <= N <= 100; 1 <= M <= 100) squares. Each square contains either water ('W') or dry land ('.'). Farmer John would like to figure out how many ponds have formed in his field. A pond is a connected set of squares with water in them, where a square is considered adjacent to all eight of its neighbors. Given a diagram of Farmer John's field, determine how many ponds he has.
由于近期的降雨,雨水汇集在农民约翰的田地不同的地方。我们用一个NxM(1<=N<=100;1<=M<=100)网格图表示。每个网格中有水('W') 或是旱地('.')。一个网格与其周围的八个网格相连,而一组相连的网格视为一个水坑。约翰想弄清楚他的田地已经形成了多少水坑。给出约翰田地的示意图,确定当中有多少水坑。
输入格式
Line 1: Two space-separated integers: N and M * Lines 2..N+1: M characters per line representing one row of Farmer John's field. Each character is either 'W' or '.'. The characters do not have spaces between them.
第1行:两个空格隔开的整数:N 和 M 第2行到第N+1行:每行M个字符,每个字符是'W'或'.',它们表示网格图中的一排。字符之间没有空格。
输出格式
Line 1: The number of ponds in Farmer John's field.
一行:水坑的数量
输入输出样例
输入 #1复制
10 12 W........WW. .WWW.....WWW ....WW...WW. .........WW. .........W.. ..W......W.. .W.W.....WW. W.W.W.....W. .W.W......W. ..W.......W.输出 #1复制
3说明/提示
OUTPUT DETAILS: There are three ponds: one in the upper left, one in the lower left, and one along the right side.
///连通块问题
#include<stdio.h>
char a[101][101];//用于保存地图
int ans,n,m;
void dfs(int x,int y)
{
//上下左右斜上方斜下方都要考虑!
int next[9][2]={{0,0},{1,1},{-1,-1},{-1,1},{1,-1},{0,1},{1,0},{-1,0},{0,-1}};
a[x][y]='.';//走过的地方标记为‘.’
int dx,dy;
for(int i=0; i<=8; i++)//搜索周围
{
dx=x+next[i][0];
dy=y+next[i][1];
if(dx>=0&&dx<=n&&dy>=0&&dy<m&&a[dx][dy]=='W')
{
dfs(dx,dy);
}
}
return;
}
int main()
{
//输入地图
scanf("%d%d",&n,&m);
for(int i=0; i<=n; i++)
{
scanf("%s",a[i]);//一次输入一行
}
for(int i=0; i<=n; i++)
{
for(int j=0; j<m; j++)
{
if(a[i][j]=='W') //遇到W开始遍历
{
dfs(i,j);
ans++;
}
}
}
printf("%d",ans);
return 0;
}
5.
题目背景
kkksc03 的大学生活非常的颓废,平时根本不学习。但是,临近期末考试,他必须要开始抱佛脚,以求不挂科。
题目描述
这次期末考试,kkksc03 需要考 44 科。因此要开始刷习题集,每科都有一个习题集,分别有 s_1,s_2,s_3,s_4s1,s2,s3,s4 道题目,完成每道题目需要一些时间,可能不等(A_1,A_2,\ldots,A_{s_1}A1,A2,…,As1,B_1,B_2,\ldots,B_{s_2}B1,B2,…,Bs2,C_1,C_2,\ldots,C_{s_3}C1,C2,…,Cs3,D_1,D_2,\ldots,D_{s_4}D1,D2,…,Ds4)。
kkksc03 有一个能力,他的左右两个大脑可以同时计算 22 道不同的题目,但是仅限于同一科。因此,kkksc03 必须一科一科的复习。
由于 kkksc03 还急着去处理洛谷的 bug,因此他希望尽快把事情做完,所以他希望知道能够完成复习的最短时间。
输入格式
本题包含 55 行数据:第 11 行,为四个正整数 s_1,s_2,s_3,s_4s1,s2,s3,s4。
第 22 行,为 A_1,A_2,\ldots,A_{s_1}A1,A2,…,As1 共 s_1s1 个数,表示第一科习题集每道题目所消耗的时间。
第 33 行,为 B_1,B_2,\ldots,B_{s_2}B1,B2,…,Bs2 共 s_2s2 个数。
第 44 行,为 C_1,C_2,\ldots,C_{s_3}C1,C2,…,Cs3 共 s_3s3 个数。
第 55 行,为 D_1,D_2,\ldots,D_{s_4}D1,D2,…,Ds4 共 s_4s4 个数,意思均同上。
输出格式
输出一行,为复习完毕最短时间。
输入输出样例
输入 #1复制
1 2 1 3 5 4 3 6 2 4 3输出 #1复制
20说明/提示
1\leq s_1,s_2,s_3,s_4\leq 201≤s1,s2,s3,s4≤20。
1\leq A_1,A_2,\ldots,A_{s_1},B_1,B_2,\ldots,B_{s_2},C_1,C_2,\ldots,C_{s_3},D_1,D_2,\ldots,D_{s_4}\leq601≤A1,A2,…,As1,B1,B2,…,Bs2,C1,C2,…,Cs3,D1,D2,…,Ds4≤60。
//本质:0/1背包问题
///把总时间的一半当作背包容量
///每个题的时间当成物体的质量
#include<stdio.h>
#include<string.h>
int max(int x,int y)
{
return(x>=y?x:y);
}
int main()
{
int k,i,j;
int ans=0;
int s[5];//储存各个科目题数
int a[25];//储存各个题目所用时间
int t[5]= {0}; //储存每个科目作业总时间
int f[5]= {0}; //储存每个科目的最优处理时间
int dp[25][2000];///tip:dp表最大宽度为20*60(想想为什么)
for(k=1; k<=4; k++)
scanf("%d",&s[k]);
for(k=1; k<=4; k++)
{
memset(dp,0,sizeof(dp));//每操作一门科目要重新初始化dp表哦
for(i=1; i<=s[k]; i++)///tip
{
scanf("%d",&a[i]);
t[k]+=a[i];
}
//printf("%d\n",t[k]);//检查
for(i=1; i<=s[k]; i++) //质量
{
for(j=1; j<=t[k]/2; j++) //总容量
{
if(j<a[i])///tip(抽象:是判断能否装下当前物品)
dp[i][j]=dp[i-1][j];
else
dp[i][j]=max(dp[i-1][j],dp[i-1][j-a[i]]+a[i]);
}
}
f[k]=t[k]-dp[s[k]][t[k]/2];//当前科目的最短时间为总时间减去dp时间
//printf("本科目所用时间为%d\n",f[k]);
}
for(i=1; i<=4; i++)
ans=ans+f[i];//把每一科的最优时间相加即得到结果
printf("%d",ans);
return 0;
}