G - 7 HDU - 1010
//DFS+奇偶剪枝
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 10;
const int maxT = 60;
char map[maxn][maxn];
int sx, sy, ex, ey; //起点坐标、终点坐标
int m, n, T; //m*n迷宫,T步
int flag; //目标:1:true,0:fail
int dir[][2] = { {0,1},{1,0},{-1,0},{0,-1} }; //四个方向走法(坐标变化)
void dfs(int x, int y, int t)
{
if (flag)return; //到达终点结束退出
if (t > T)return; //超时退出
if (x == ex && y == ey && t == T) //到达终点,flag赋值
{
flag = 1;
return;
}
int left_t = abs(x - ex) + abs(y - ey); //到达终点需要的最少步数
int temp = T - t - left_t; //剩余时间-最短时间
if (temp & 1)return; //奇数,不能到达,退出
for (int i = 0; i < 4; i++) //四个方向搜索
{
int temp_x = x + dir[i][0];
int temp_y = y + dir[i][1];
if (map[temp_x][temp_y] == 'X' || x<1 || x>n || y<1 || y>m) continue; //遇到墙,返回循环
map[temp_x][temp_y] = 'X'; //不是墙,前进,设为新起点(起点不可走,设为墙)
dfs(temp_x, temp_y, t + 1); //递归
map[temp_x][temp_y] = '.'; //将走过的点还原成路
}
}
int main()
{
while (cin >> n >> m >> T && m || n || T)
{
int num = 0;
for (int i = 1; i <= n; i++) //n行
for (int j = 1; j <= m; j++) //m列
{
cin >> map[i][j]; //输入地图
if (map[i][j] == 'S') //起点
{
sx = i;
sy = j;
map[i][j] = 'X'; //标为墙(不可走)
}
if (map[i][j] == 'D') //终点
{
ex = i;
ey = j;
}
if (map[i][j] == 'X') //墙
{
num++; //计算墙数
}
}
flag = 0;
if (n*m - num >= T) //可走步数>=时间(需要走的步数)
dfs(sx, sy, 0);
if (flag)cout << "YES" << endl;
else
cout << "NO" << endl;
}
return 0;
}
I - 9 HDU - 2049
错排问题
//不知为何ac不了
#include <iostream>
using namespace std;
const int maxn = 25;
long long num[maxn];
long long derangement1(int n) //法1
{
num[1] = 0;
num[2] = 1;
for (int i = 3; i <= n; ++i)
{
int symbol;
symbol = (i % 2 == 0 ? 1 : -1);
num[i] = i*num[i - 1]+symbol;
// cout << "num[" << i << "]=" << num[i] << endl;
}
return num[n];
}
long long derangement2(int n) //法2
{
num[1] = 0;
num[2] = 1;
for (int i = 3; i <= n; ++i)
{
num[i] = (i-1)*(num[i - 2] + num[i - 1]);
// cout << "num[" << i << "]=" << num[i] << endl;
}
return num[n];
}
long long CN(int a, int b) //组合数
{
if (a == b) return 1;
if (b == 0) return 1;
b > a / 2 ? b = b : b = a - b;
long long A = 1, B = 1;
for (int i = a; i > 0; --i)
{
A = A * i;
}
for (int t = b; t > 0; --t)
{
B = B * t;
}
return A / B;
}
int main()
{
derangement1(25);
// derangement2(25);
int N, M,n;
cin >> n;
long long *ans=NULL;
ans = new long long[n];
int r = 0;
int T = n;
while (n--)
{
cin >> N >> M;
ans[r++]=CN(N, N-M)*derangement1(M);
}
for (int i=0; i < T; ++i)
{
cout << ans[i] << endl;
}
}
J - 0 HDU - 2067
最短路径的迷宫问题
方法:构造地图,计算每个位置到达的路径数,逐个推导。
#include <iostream>
using namespace std;
int main()
{
int n;
int ansN = 1;
while (cin >> n, n != -1)
{
long long int **p = new int long long *[n+1]; //注意类型
for (int i = 0; i <= n; ++i)
{
p[i] = new long long int[n+1];
}
p[0][0] = 1;
for (int i = 1; i <= n; ++i) //在最短路径条件下,只能向右走或向下走
{
for (int t = 0; t <= i; ++t)
{
if (t == 0) p[i][t] = p[i - 1][t]; //每行第一个位置只能由上一行的第一个位置向下走
if(t!=0&&i!=t) p[i][t] = p[i][t - 1] + p[i - 1][t]; //在非对角线位置,每个位置为上方位置往下走,左边位置往右走,两者数量求和
if (i == t) p[i][t] = p[i][t - 1]; //终点位置路径数等于左边位置路径数
}
}
cout << ansN++<<' '<<n<<' '<<p[n][n] * 2<<endl;
}
}