• wenbao与记忆化搜索


    记忆化搜索:

    通俗地讲就是搜索的形式,dp的思想

    一些搜索难以完成,dp的动态转移方程又不好写的题,就会用到记忆化搜索,利用dp记录路径(相当于为dfs剪枝)用dfs进行模拟。。

    啦啦啦啦啦啦,,,,,,,,,好厉害!!!!!!

    @  https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1059

    弱鸡代码

     1 #include <string.h>
     2 #include <iostream>
     3 #include <stdio.h>
     4 using namespace std;
     5 int a[4][44], dp[44][44][44][44], num[4], n;
     6 bool flag[44];
     7 int dfs(int count){
     8     if(dp[num[0]][num[1]][num[2]][num[3]] != -1) 
     9         return dp[num[0]][num[1]][num[2]][num[3]];
    10     if(count == 5)
    11         return dp[num[0]][num[1]][num[2]][num[3]] = 0;
    12     int sum = 0;
    13     for(int i = 0; i < 4; i++){
    14         if(num[i] == n) continue;
    15         int color = a[i][num[i]];
    16         num[i] += 1;
    17         if(flag[color]){
    18             flag[color] = false;
    19             sum = max(sum, dfs(count-1)+1);
    20             flag[color] = true;
    21         }
    22         else{
    23             flag[color] = true;
    24             sum = max(sum, dfs(count+1));
    25             flag[color] = false;
    26         }
    27         num[i] -=1 ;
    28     } 
    29     return dp[num[0]][num[1]][num[2]][num[3]] = sum;
    30 }
    31 int main(){
    32     while(scanf("%d", &n) && n){
    33         memset(dp, -1, sizeof(dp));
    34         memset(flag, false, sizeof(flag));
    35         memset(num, 0 ,sizeof(num));
    36         for(int i = 0; i < n; i++){
    37             for(int j = 0; j < 4; j++){
    38                 cin>>a[j][i];
    39             }
    40         }
    41         num[0] = num[1] = num[2] = num[3] = 0;
    42         cout<<dfs(0)<<endl;
    43     }
    44     return 0;
    45 }

    @  http://acm.hdu.edu.cn/showproblem.php?pid=1078

    给定一个n*n的地图,最多只能走k步并且保证下一个点的值大于原来的点,求可以得到的最大值

    开始故意用纯dfs试了下果然超时。。。。。

    垃圾代码:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 using namespace std;
     5 int a[105][105], dp[105][105], n, m;
     6 int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
     7 int dfs(int r, int c){
     8     int ma = 0;
     9     if(dp[r][c]<0){
    10         for(int j = 1; j <= m; j++){
    11             for(int i = 0; i < 4; i++){
    12                 int rx = r + dir[i][0]*j;
    13                 int cx = c + dir[i][1]*j;
    14                 if(rx >=0 && rx < n && cx >= 0 && cx <n && a[rx][cx] > a[r][c]){
    15                     ma = max(ma,dfs(rx, cx));
    16                 }
    17             }
    18         }
    19         dp[r][c] = ma + a[r][c];
    20     }
    21     return dp[r][c];
    22 }
    23 int main(){
    24     while(scanf("%d %d", &n, &m)){
    25         if(n == -1 && m == -1) break;
    26         else{
    27             for(int i = 0; i < n; i++){
    28                 for(int j = 0; j < n; j++){
    29                     scanf("%d", &a[i][j]);
    30                     dp[i][j] = -1;
    31                 }
    32             }
    33             printf("%d
    ", dfs(0, 0));
    34         }
    35     }
    36     return 0;
    37 }

    @  玲珑杯:::::::

    http://www.ifrog.cc/acm/problem/1032

    n个球放在m个盒子里面,要求放最多球的盒子数唯一,(可以放零个球), 求最多的放法

    明显的记忆化搜索

    垃圾代码

     1 #include <iostream>
     2 #include <string.h>
     3 using namespace std;
     4 #define ll long long
     5 const ll mod = 998244353;
     6 ll dp[505][505], n, m, num = 0;
     7 ll dfs(ll he, ll qiu, ll ma){
     8     if(he == 0){
     9         if(qiu == 0) return 1;
    10         else return 0;
    11     }
    12     if(dp[he][qiu]) return dp[he][qiu];
    13     ll mam = 0;
    14     for(int i = 0; i < ma && i <=qiu; i++){
    15         mam += dfs(he-1, qiu-i, ma);
    16         mam %= mod;
    17     }
    18     dp[he][qiu] = mam;
    19     return mam;
    20 }
    21 int main(){
    22     cin>>n>>m;
    23     for(int i = n; i >=0; i--){
    24         memset(dp, 0, sizeof(dp));
    25         num += dfs(m-1, n-i, i);
    26         num %= mod;
    27     }
    28     cout<<num*m%mod<<endl;
    29     return 0;
    30 }

    @  http://acm.hdu.edu.cn/showproblem.php?pid=1978

    啦啦啦啦啦, 1A的感觉真是太爽了!!!可能这就是坚持的理由,,经过拼搏换来的快乐才是最大的快乐!!!!

    从(0, 0) 点到(n-1, m-1) 点一共有多少种走法(只可以向右向下走)

     1 #include <iostream>
     2 using namespace std;
     3 #define ll long long 
     4 const int mod = 10000;
     5 int a[105][105], dp[105][105], n, m, t;
     6 int dir[2][2] = {0, 1, 1, 0};
     7 int dfs(int r, int c, int sum){
     8     if(r == n-1 && c == m-1) return 1;
     9     ll cot = 0;
    10     if(dp[r][c] < 0){
    11         for(int i = 0; i <= sum; i++){
    12             for(int j = 0; j <= sum - i; j++){
    13                 if(i == 0 && j == 0) continue;
    14                 int rx = r + i;
    15                 int cx = c + j;
    16                 if(rx >= 0 && rx < n && cx >= 0 && cx < m){
    17                     cot += dfs(rx, cx, a[rx][cx]);
    18                     cot %= mod;
    19                 }
    20             }
    21         }
    22         dp[r][c] = cot;
    23     }
    24     return dp[r][c];
    25 }
    26 int main(){
    27     cin>>t;
    28     while(t--){
    29         cin>>n>>m;
    30         for(int i = 0; i < n; i++){
    31             for(int j = 0; j < m; j++){
    32                 cin>>a[i][j];
    33                 dp[i][j] = -1;
    34             }
    35         }
    36         cout<<dfs(0, 0, a[0][0])<<endl;
    37     }
    38     return 0;
    39 }

     -------------------------------------------

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1455

    关键在于跳的次数不会很大

     1 #include "iostream"
     2 #include <string.h>
     3 using namespace std;
     4 
     5 const int maxn = 30009;
     6 int sum[maxn][777], num[maxn], n, d, num2[maxn];
     7 bool vis[maxn][777];
     8 
     9 int dd(int pos, int l) {
    10     if(pos > 30000) return 0;
    11     if(sum[pos][l] != -1) return sum[pos][l];
    12     sum[pos][l] = num[pos];
    13     int cnt = 0;
    14     cnt = max(cnt, dd(pos+l+1-300+d, l+1));
    15     cnt = max(cnt, dd(pos+l-300+d, l));
    16     if(l+d-300 > 1) cnt = max(cnt, dd(pos+l-300-1+d, l-1));
    17     sum[pos][l] += cnt;
    18     return sum[pos][l];
    19 }
    20 
    21 int main() {
    22     int x;
    23     scanf("%d%d", &n, &d);
    24     for(int i = 0; i < n; ++i) {
    25         scanf("%d", &x);
    26         num[x] ++;
    27     }
    28     memset(sum, -1, sizeof(sum));
    29     printf("%d
    ", dd(d, 300));
    30     return 0;
    31 }

    只有不断学习才能进步!

  • 相关阅读:
    如何使用Vue原生组件编译应用程序主题?这个工具不要错过
    BTC系统中具体的区块信息
    hash(哈希)
    比特币共识协议
    计算多分类softmax的loss function
    逻辑回归0.环境设定
    分布式共识
    Hash pointer(哈希指针)
    数字货币中经常出现的问题
    比特币激励机制
  • 原文地址:https://www.cnblogs.com/wenbao/p/5869781.html
Copyright © 2020-2023  润新知