Update 2019.8.23
最近发现小绿本(《算法竞赛入门经典——习题与解答》)上的题值得一做,题解都写得很清真,不会像某谷上的题解,有一些奇技淫巧,不看 C o d e C o d e 的情况下一般都可以打出来,提高自己的代码实现能力。
然后我就先从动态规划开始吧 q w q q w q ~~
小紫书
例题:9-1
第一次打的时候用的是 E m a c s E m a c s ,然后我的配置文件有一点问题,然后编译以后代码就被吃了。。。。
劳资又 tm 打了一遍。。。。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std ;
const int MAXN = 1e3 + 5 ;
const int MAXT = 1e3 + 5 ;
const int INF = (1 << 30 );
int n, m, t, dis[MAXN], f[MAXN][MAXT];
bool flag[MAXN][MAXT][2 ];
inline void Init () {
memset (dis, 0 , sizeof (dis));
memset (flag, false , sizeof (flag));
memset (f, 0 , sizeof (f));
return ;
}
int main () {
int cnt = 0 ;
while (true ) {
Init ();
cnt ++;
scanf ("%d" , &n);
if (n == 0 ) {
break ;
}
scanf ("%d" , &t);
for (int i = 1 ; i <= n - 1 ; i++) {
scanf ("%d" , &dis[i]);
}
scanf ("%d" , &m);
for (int i = 1 ; i <= m; i++) {
int temp;
scanf ("%d" , &temp);
for (int j = 1 ; j <= n; j++) {
flag[j][temp][0 ] = true ;
temp += dis[j];
}
}
scanf ("%d" , &m);
for (int i = 1 ; i <= m; i++) {
int temp;
scanf ("%d" , &temp);
for (int j = n; j >= 1 ; j--) {
flag[j][temp][1 ] = true ;
temp += dis[j - 1 ];
}
}
for (int i = 1 ; i <= n; i++) {
f[i][t] = INF;
}
f[n][t] = 0 ;
for (int i = t - 1 ; i >= 0 ; i--) {
for (int j = 1 ; j <= n; j++) {
f[j][i] = f[j][i + 1 ] + 1 ;
if (j < n && flag[j][i][0 ] && i + dis[j] <= t) {
f[j][i] = min (f[j][i], f[j + 1 ][i + dis[j]]);
}
if (j > 1 && flag[j][i][1 ] && i + dis[j - 1 ] <= t) {
f[j][i] = min (f[j][i], f[j - 1 ][i + dis[j - 1 ]]);
}
}
}
printf ("Case Number %d: " , cnt);
if (f[1 ][0 ] >= INF) {
printf ("impossible\n" );
}
else printf ("%d\n" , f[1 ][0 ]);
}
return 0 ;
}
小绿书—《习题与解答》
1.最长的滑雪路径
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std ;
const int MAXRC = 1e2 + 5 ;
const int cmp[4 ][2 ]={{1 ,0 },{-1 ,0 },{0 ,1 },{0 ,-1 }};
int T, r, c, ans ;
int data[MAXRC][MAXRC],dp[MAXRC][MAXRC];
char ch[MAXRC];
inline void Init () {
ans=0 ;
memset (data,0 ,sizeof (data));
memset (dp,0 ,sizeof (dp));
return ;
}
void DP (int x,int y) {
for (int i=0 ;i<4 ;i++){
int tox=x+cmp[i][0 ];
int toy=y+cmp[i][1 ];
if (tox<1 ||tox>r||toy<1 ||toy>c) continue ;
if (data[tox][toy]<data[x][y]){
if (!dp[tox][toy]){
dp[tox][toy]=1 ;
DP(tox,toy);
}
dp[x][y]=max(dp[x][y],dp[tox][toy]+1 );
}
}
ans=max(ans,dp[x][y]);
return ;
}
int main () {
scanf ("%d" ,&T);
while (T--) {
scanf ("%s" , ch);
printf ("%s: " , ch);
Init();
scanf ("%d%d" , &r, &c);
for (int i=1 ;i<=r;i++)
for (int j=1 ;j<=c;j++)
scanf ("%d" ,&data[i][j]);
for (int i=1 ;i<=r;i++){
for (int j=1 ;j<=c;j++){
if (dp[i][j])
continue ;
dp[i][j]=1 ;
DP(i,j);
}
}
printf ("%d\n" ,ans);
}
return 0 ;
}
2.免费糖果
题目链接:[洛谷 ]|[UVA(科学上网) ]
分析:用 d p [ a , b , c , d ] d p [ a , b , c , d ] 来表示 4 个队列的拿取情况所对应口袋中的糖数。枚举每一种情况,如果篮子里有这种糖果了,就把篮子相应的糖果 − 1 − 1 ;反之, + 1 + 1 。可以使用记忆化搜索实现,这样可以去除大量重复情况。
C o d e C o d e :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std ;
const int MAXN=45 ;
int data[5 ][MAXN],n;
int dp[MAXN][MAXN][MAXN][MAXN];
int top[5 ];
inline void Init () {
top[1 ]=top[2 ]=top[3 ]=top[4 ]=1 ;
memset (dp,-1 ,sizeof (dp));
return ;
}
int dfs (int cnt,bool flag[]) {
int ans=0 ;
int a=top[1 ];
int b=top[2 ];
int c=top[3 ];
int d=top[4 ];
if (dp[a][b][c][d]!=-1 ) return dp[a][b][c][d];
if (cnt==5 ) return dp[a][b][c][d]=0 ;
for (int i=1 ;i<=4 ;i++){
if (top[i]>n) continue ;
int to=data[i][top[i]];
top[i]++;
if (flag[to]){
flag[to]=false ;
ans=max(ans,dfs(cnt-1 ,flag)+1 );
flag[to]=true ;
}
else {
flag[to]=true ;
ans=max(ans,dfs(cnt+1 ,flag));
flag[to]=false ;
}
top[i]--;
}
dp[a][b][c][d]=ans;
return dp[a][b][c][d];
}
int main () {
while (true ){
scanf ("%d" ,&n);
if (!n) return 0 ;
Init();
bool flag[MAXN];
memset (flag,false ,sizeof (flag));
for (int i=1 ;i<=n;i++)
for (int j=1 ;j<=4 ;j++)
scanf ("%d" ,&data[j][i]);
printf ("%d\n" ,dfs(0 ,flag));
}
return 0 ;
}
评论
发表评论