鱼C论坛

 找回密码
 立即注册
查看: 1142|回复: 12

[已解决]关于记忆化搜索程序求调

[复制链接]
发表于 2023-7-7 01:07:10 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
一道题目求调,关于记忆化搜索
https://www.luogu.com.cn/problem/P1060

另外,有谁可以推荐一个免费chatgpt镜像吗,谢谢了

  1. #include <stdio.h>
  2. #define max(a,b) (a)>(b)?(a):(b)

  3. long long v[28],p[28],mem[28][30001];

  4. long long dp(int x,int s)
  5. {
  6.         if(mem[x][s]!=0) return mem[x][s];
  7.         if(x==0)
  8.         {
  9.                 if(v[0]>s)
  10.                 {
  11.                         return 0;
  12.                 }
  13.                 return v[0]*p[0];
  14.         }
  15.        
  16.         if(v[x]>s)
  17.         {
  18.                 mem[x-1][s]=dp(x-1,s);
  19.                 return mem[x-1][s];
  20.         }
  21.         if(mem[x-1][s-v[x]]==0) mem[x-1][s-v[x]]=v[x]*p[x]+dp(x-1,s-v[x]);
  22.         if(mem[x-1][s]==0) mem[x-1][s]=dp(x-1,s);
  23.         return max(mem[x-1][s-v[x]],mem[x-1][s]);
  24. }

  25. int main()
  26. {
  27.         int n,m;
  28.         scanf("%d%d",&n,&m);
  29.         for(int i=0;i<m;i++)
  30.         {
  31.                 scanf("%lld%lld",&v[i],&p[i]);
  32.         }
  33.         printf("%lld\n",dp(m-1,n));
  34.         return 0;
  35. }
复制代码


主要是看记忆化哪里逻辑不对,我一直找不到
@zhangjinxuan @元豪 @sfqxx
最佳答案
2023-7-8 13:16:59
本帖最后由 python/print 于 2023-7-8 13:25 编辑
额外减小 发表于 2023-7-7 18:03
但我提问的主要目的是看我思维逻辑哪里有问题,算出来答案为什么不同


(求最佳答案)
  1. 这段代码是背包问题的解法,但是存在以下几处错误:
  2. 1. 在主函数中,读入的物品个数m应该为m+1,因为物品的编号是从0到m-1。所以第一个循环应该是for(int i=0;i<=m;i++)。
  3. 2. 在dp函数中,第一个if条件语句判断v[0]与s的大小关系时,应该是if(v[0]>s),而不是if(v[0]>=s),因为根据题目描述,可以等于总钱数N。
  4. 3. 在第一个if条件语句中,需要添加对mem[0][s]的更新,即mem[0][s] = v[0] * p[0];,以确保初始问题的结果被正确保存到mem数组中。
复制代码
  1. (没办法,上面[s]貌似和论坛的冲突了,只能用代码框)
复制代码


代码如下:

  1. #include <stdio.h>
  2. #define max(a,b) (a)>(b)?(a):(b)

  3. long long v[28],p[28],mem[28][30001];

  4. long long dp(int x,int s)
  5. {
  6.         if(mem[x][s]!=0) return mem[x][s];
  7.         if(x==0)
  8.         {
  9.                 if(v[0]>s)
  10.                 {
  11.                         return 0;
  12.                 }
  13.                 mem[0][s] = v[0] * p[0]; // 更新初始问题的结果
  14.                 return mem[0][s];
  15.         }
  16.         
  17.         if(v[x]>s)
  18.         {
  19.                 mem[x-1][s]=dp(x-1,s);
  20.                 return mem[x-1][s];
  21.         }
  22.         if(mem[x-1][s-v[x]]==0) mem[x-1][s-v[x]]=v[x]*p[x]+dp(x-1,s-v[x]);
  23.         if(mem[x-1][s]==0) mem[x-1][s]=dp(x-1,s);
  24.         return max(mem[x-1][s-v[x]],mem[x-1][s]);
  25. }

  26. int main()
  27. {
  28.         int n,m;
  29.         scanf("%d%d",&n,&m);
  30.         for(int i=0;i<=m;i++) // 修改循环条件
  31.         {
  32.                 scanf("%lld%lld",&v[i],&p[i]);
  33.         }
  34.         printf("%lld\n",dp(m,n)); // 修改参数传递
  35.         return 0;
  36. }
复制代码


但是 这个思路可能还是解不了一些节点,我也不知道怎么回事,WA了,但是按照下方思路来,我试过是AC的
  1. 这个就是背包问题,可以使用动态规划来解决。
  2. 首先,创建一个二维数组dp[m+1][N+1],其中dp[j]表示在考虑前i件物品、总钱数不超过j的情况下,所能达到的最大总和。
  3. 然后,我们可以使用以下递推关系式来填充dp数组:
  4. dp[j] = max(dp[i-1][j], dp[i-1][j-v] + v*w)
  5. 其中v表示第i件物品的价格,w表示第i件物品的重要度。
  6. 最后,所求的答案即为dp[m][N]。
复制代码


小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-7-7 06:50:39 | 显示全部楼层
别问我,我不会
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-7 06:56:52 | 显示全部楼层
可不可以用贪心?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-7 06:58:35 | 显示全部楼层
元豪 发表于 2023-7-7 06:56
可不可以用贪心?

额,好像不行

算了 @zhangjinxuan
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-7 08:24:48 | 显示全部楼层
题不会,镜像还是可以给你的
https://c.binjie.fun/

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
额外减小 + 3 + 3

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-7 11:10:43 | 显示全部楼层
liuhongrun2022 发表于 2023-7-7 08:24
题不会,镜像还是可以给你的
https://c.binjie.fun/

github.com/xx025/carrot
你看issue,这个还是我提的,是在jinshutuan被墙那天偶然在jinshutuan上看见的
然后jinshutuan当天下午就无法访问了
于是我就去了cbinjiefun,过了几天看github.com/xx025/carrot上还没有就顺便提了一个issue

点评

https://github.com/xx025/carrot/issues/641  发表于 2023-7-7 11:11

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
额外减小 + 3 + 3

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-7 12:59:28 | 显示全部楼层
这个就是背包问题,可以使用动态规划来解决。
首先,创建一个二维数组dp[m+1][N+1],其中dp[i][j]表示在考虑前i件物品、总钱数不超过j的情况下,所能达到的最大总和。
然后,我们可以使用以下递推关系式来填充dp数组:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-v[i]] + v[i]*w[i])
其中v[i]表示第i件物品的价格,w[i]表示第i件物品的重要度。
最后,所求的答案即为dp[m][N]。
C++代码如下:
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>

  4. using namespace std;

  5. int main() {
  6.     int N, m;
  7.     cin >> N >> m;

  8.     vector<int> v(m+1);
  9.     vector<int> w(m+1);
  10.     vector<vector<int>> dp(m+1, vector<int>(N+1));

  11.     for (int i = 1; i <= m; i++) {
  12.         cin >> v[i] >> w[i];
  13.     }

  14.     for (int i = 1; i <= m; i++) {
  15.         for (int j = 1; j <= N; j++) {
  16.             if (j >= v[i]) {
  17.                 dp[i][j] = max(dp[i-1][j], dp[i-1][j-v[i]] + v[i]*w[i]);
  18.             } else {
  19.                 dp[i][j] = dp[i-1][j];
  20.             }
  21.         }
  22.     }

  23.     cout << dp[m][N] << endl;

  24.     return 0;
  25. }
复制代码


(CHATGPT国内版)
  1. https://www.wetab.link/
复制代码

这个是浏览器插件,目前使用体验还是非常好的。(其会修改新标签页,请允许及插件行为)
需要登录。登录后里面有个Chat AI,点进去就可以问问题。

求最佳答案!

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
额外减小 + 3 + 3

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-7 18:01:55 | 显示全部楼层
元豪 发表于 2023-7-7 06:56
可不可以用贪心?

不行吧。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-7 18:03:18 | 显示全部楼层
python/print 发表于 2023-7-7 12:59
这个就是背包问题,可以使用动态规划来解决。
首先,创建一个二维数组dp[m+1][N+1],其中dp[j]表示在考虑 ...

但我提问的主要目的是看我思维逻辑哪里有问题,算出来答案为什么不同
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-8 13:16:59 | 显示全部楼层    本楼为最佳答案   
本帖最后由 python/print 于 2023-7-8 13:25 编辑
额外减小 发表于 2023-7-7 18:03
但我提问的主要目的是看我思维逻辑哪里有问题,算出来答案为什么不同


(求最佳答案)
  1. 这段代码是背包问题的解法,但是存在以下几处错误:
  2. 1. 在主函数中,读入的物品个数m应该为m+1,因为物品的编号是从0到m-1。所以第一个循环应该是for(int i=0;i<=m;i++)。
  3. 2. 在dp函数中,第一个if条件语句判断v[0]与s的大小关系时,应该是if(v[0]>s),而不是if(v[0]>=s),因为根据题目描述,可以等于总钱数N。
  4. 3. 在第一个if条件语句中,需要添加对mem[0][s]的更新,即mem[0][s] = v[0] * p[0];,以确保初始问题的结果被正确保存到mem数组中。
复制代码
  1. (没办法,上面[s]貌似和论坛的冲突了,只能用代码框)
复制代码


代码如下:

  1. #include <stdio.h>
  2. #define max(a,b) (a)>(b)?(a):(b)

  3. long long v[28],p[28],mem[28][30001];

  4. long long dp(int x,int s)
  5. {
  6.         if(mem[x][s]!=0) return mem[x][s];
  7.         if(x==0)
  8.         {
  9.                 if(v[0]>s)
  10.                 {
  11.                         return 0;
  12.                 }
  13.                 mem[0][s] = v[0] * p[0]; // 更新初始问题的结果
  14.                 return mem[0][s];
  15.         }
  16.         
  17.         if(v[x]>s)
  18.         {
  19.                 mem[x-1][s]=dp(x-1,s);
  20.                 return mem[x-1][s];
  21.         }
  22.         if(mem[x-1][s-v[x]]==0) mem[x-1][s-v[x]]=v[x]*p[x]+dp(x-1,s-v[x]);
  23.         if(mem[x-1][s]==0) mem[x-1][s]=dp(x-1,s);
  24.         return max(mem[x-1][s-v[x]],mem[x-1][s]);
  25. }

  26. int main()
  27. {
  28.         int n,m;
  29.         scanf("%d%d",&n,&m);
  30.         for(int i=0;i<=m;i++) // 修改循环条件
  31.         {
  32.                 scanf("%lld%lld",&v[i],&p[i]);
  33.         }
  34.         printf("%lld\n",dp(m,n)); // 修改参数传递
  35.         return 0;
  36. }
复制代码


但是 这个思路可能还是解不了一些节点,我也不知道怎么回事,WA了,但是按照下方思路来,我试过是AC的
  1. 这个就是背包问题,可以使用动态规划来解决。
  2. 首先,创建一个二维数组dp[m+1][N+1],其中dp[j]表示在考虑前i件物品、总钱数不超过j的情况下,所能达到的最大总和。
  3. 然后,我们可以使用以下递推关系式来填充dp数组:
  4. dp[j] = max(dp[i-1][j], dp[i-1][j-v] + v*w)
  5. 其中v表示第i件物品的价格,w表示第i件物品的重要度。
  6. 最后,所求的答案即为dp[m][N]。
复制代码


小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 0 反对 1

使用道具 举报

 楼主| 发表于 2023-7-10 15:50:01 | 显示全部楼层

你确定不是用chatgpt回答的吧。这个回答的语言逻辑上可能有点问题。不过我试了下顺推还是能过的,那就给你最佳了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-11 11:11:05 | 显示全部楼层
额外减小 发表于 2023-7-10 15:50
你确定不是用chatgpt回答的吧。这个回答的语言逻辑上可能有点问题。不过我试了下顺推还是能过的,那就给 ...

GPT一般会回答这个是典型的xxx问题

评分

参与人数 1荣誉 +1 收起 理由
额外减小 + 1

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-26 20:58

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表