E - 5 HDU - 1078
dfs
#include <iostream>
#include <algorithm>
using namespace std;
int n, k;
int p[101][101];
int dp[101][101];
int dx[4] = { 0,1,0,-1 };
int dy[4] = { 1,0,-1,0 };
void dfs(int x,int y)
{
for (int i = 0; i < 4; ++i) //四个方向
{
for (int t = 1; t <= k; ++t) //走1--k步
{
int tx = x + t * dx[i]; //temp坐标
int ty = y + t * dy[i];
if (tx >= 0 && ty >= 0 && tx < n && ty < n)
{
if (p[tx][ty] > p[x][y])
{
if (dp[tx][ty] == 0)
{
dfs(tx, ty);
dp[x][y] = max(dp[x][y], dp[tx][ty] + p[x][y]);
}
else
{
dp[x][y] = max(dp[x][y], dp[tx][ty] + p[x][y]);
}
}
}
}
}
if (dp[x][y] == 0) dp[x][y] = p[x][y];
return;
}
int main()
{
while (cin >> n >> k)
{
if (n == -1&&k==-1) break;
for (int i = 0; i < n; ++i)
{
for (int t = 0; t < n; ++t)
cin >> p[i][t];
}
memset(dp, 0, sizeof(dp));
dfs(0, 0);
cout << dp[0][0] << endl;
}
}
F - 6 HDU - 1072
定时走迷宫+时间重置
思路:dfs+剪枝(也可用bfs做)
#include <iostream>
#include <cstring>
using namespace std;
int n, m;
int time[8][8],step[8][8];
int tim, st;
int minstep;
const int inf = 9999;
int map[8][8];
int dx[4] = { 0,1,0,-1 };
int dy[4] = { 1,0,-1,0 };
void dfs(int sx, int sy,int tim,int st)
{
if (sx<0 || sx>=n || sy<0 || sy>=m) return;
if (st >= minstep || tim <= 0) return;
if (map[sx][sy] == 0) return;
if (map[sx][sy] == 3) //到达目标
{
if (st < minstep) minstep = st;
return;
}
if (map[sx][sy] == 4) tim = 6;
if (st >= step[sx][sy] && time[sx][sy] >= tim) return; //剪枝
step[sx][sy] = st ;
time[sx][sy] = tim ;
for (int i = 0; i < 4; ++i)
{
int tx = sx + dx[i];
int ty = sy + dy[i];
dfs(tx, ty,tim-1,st+1);
}
}
int main()
{
int T;
cin >> T;
while (T--)
{
cin >> n >> m;
int sx, sy, ex, ey;
for (int i = 0; i < n; ++i)
{
for (int t = 0; t < m; ++t)
{
cin >> map[i][t];
if (map[i][t] == 2)
{
sx = i; sy = t;
}
if (map[i][t] == 3)
{
ex = i; ey = t;
}
}
}
memset(step, inf, sizeof(step)); //初始化为inf,不是0
memset(time, 0, sizeof(time));
time[sx][sy] = 6;
tim = 6; st = 0; minstep = inf;
dfs(sx, sy,6,0);
if (minstep == inf) cout << -1 << endl;
else cout << minstep << endl;
// cout << step[ex][ey] << endl;
}
}
H - 8 UVA - 11389
贪心问题
方法:先对早、晚班车时长排序(一个升序,一个降序,之后对应项相加与d比较,计算出超时总量即可)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
void upsort(int a[], int n) //升序
{
for (int i = 0; i < n - 1; ++i)
{
for (int t = i + 1; t < n; ++t)
{
if (a[i] > a[t])
{
int x = a[i];
a[i] = a[t];
a[t] = x;
}
}
}
}
void downsort(int a[], int n) //降序
{
for (int i = 0; i < n - 1; ++i)
{
for (int t = i + 1; t < n; ++t)
{
if (a[i] < a[t])
{
int x = a[i];
a[i] = a[t];
a[t] = x;
}
}
}
}
int main()
{
int n, d, r;
int mo[105], en[105];
while (cin >> n >> d >> r)
{
if (n ==0 &&d ==0&& r == 0) break;
memset(mo, n, 0);
memset(en, n, 0);
for (int i = 0; i < n; ++i)
{
cin >> mo[i];
}
upsort(mo, n);
for (int i = 0; i < n; ++i)
{
cin >> en[i];
}
downsort(en, n);
int s = 0;
for (int i = 0; i < n; ++i)
{
int f = mo[i] + en[i];
if (f > d)
{
s = s + f - d;
}
}
cout << s * r << endl;
}
}
I - 9 HDU - 1754
//线段树 - 老师询问 - 套模板(24号HDU - 1166线段树:把sum改为记录最大值)
#include <iostream>
using namespace std;
//HDU - 1166线段树模板修改
const int maxn = 200001;
int n,m; //n个数,m条命令
int p[maxn];
int s;
struct node
{
int l;
int r;
int max;//储存最大值
}t[maxn << 2];
void build(int l, int r, int idx) //l:左边界,r:右边界,idx:下标
{
t[idx].l = l;
t[idx].r = r;
if (l == r)
{
t[idx].max = p[l];
return;
}
else
{
int mid = (t[idx].l + t[idx].r) >> 1;
build(l, mid, (idx << 1) + 1); //左子树;重点理解下标idx的变化
build(mid + 1, r, (idx << 1) + 2); //右子树
t[idx].max =( t[(idx << 1) | 1].max > t[(idx << 1) + 2].max ? t[(idx << 1) | 1].max : t[(idx << 1) + 2].max); //父节点存储左右子树大的数值
}
}
int query(int l, int r, int idx) //查询
{
if (l <= t[idx].l&&r >= t[idx].r)
{
// cout << "s=s+t[idx].sum=" << s << '+' << t[idx].sum<<endl;
if(t[idx].max>s) s = t[idx].max; //注意这个if条件,否则递归过程s会被还原
if (l == t[idx].l&&r == t[idx].r)
{
if (t[idx].max > s) s = t[idx].max;
return s;
}
}
else
{
int mid = (t[idx].l + t[idx].r) >> 1;
if (r <= mid)
{
int x=query(l, r, (idx << 1) | 1);
if (x > s) s = x;
}
else if (l > mid)
{
int x=query(l, r, (idx << 1) + 2);
if (x > s) s = x;
}
else
{
int x=query(l, mid, (idx << 1) | 1); //询问左子树
if (x > s) s = x;
int y=query(mid + 1, r, (idx << 1) + 2); //询问右子树
if (y > s) s = y;
}
}
}
void update(int i, int idx, int val)//
{
p[i] = val;
if(val>t[idx].max) t[idx].max = val; //修改sum
if (t[idx].l == i && i == t[idx].r) return;
else
{
int mid = (t[idx].l + t[idx].r) >> 1;
if (i <= mid) update(i, (idx << 1) | 1, val);
else update(i, (idx << 1) + 2, val);
}
}
int main()
{
while (cin >> n >> m)
{
for (int i = 1; i <= n; ++i)
{
cin >> p[i];
}
build(1, n, 0);
/* for (int i = 0; i < 30; ++i)
{
cout << t[i].sum << ' ';
}cout << endl;*/
char op;
while (m--)
{
cin >> op;
int a, b;
cin >> a >> b;
if (op == 'Q')
{
s = 0;
query(a, b, 0);
printf("%d\n", s);
// cout << s << endl;
}
else if (op == 'U')
{
update(a, 0, b);
}
/* for (int i = 0; i < 30; ++i)
{
cout << t[i].sum << ' ';
}cout << endl<<endl;*/
}
}
}