当前位置:   article > 正文

2.7学习总结

2.7学习总结

2.7
1.蓝桥王国(dijkstra
2.吃奶酪
3.榨取kkksc03
4.补给

蓝桥王国https://www.lanqiao.cn/problems/1122/learning/?page=1&first_category_id=1&name=%E8%93%9D%E6%A1%A5%E7%8E%8B%E5%9B%BD

dijkstra板子题,主要是运用优先队列完成

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define lowbit(x) (x& - (x))
  4. #define int long long
  5. const int INF=0x3f3f3f3f3f3f3f3fLL;
  6. const int N=3e5+5;;
  7. struct edge{
  8. int from,to,w;
  9. edge(int a,int b,int c){
  10. from=a;
  11. to=b;
  12. w=c;
  13. }
  14. }; //这个主要是保存图中每个节点的邻居节点
  15. vector<edge>e[N];
  16. struct s_node{
  17. int id,n_dis; //输入优先队列的成员
  18. s_node(int a,int b){
  19. id=a;
  20. n_dis=b;
  21. }
  22. bool operator < (const s_node & a)const { //用重载运算符,这个是结构体的写法
  23. return n_dis>a.n_dis;
  24. }
  25. };
  26. int n,m;
  27. int pre[N]; //主要用于记录前驱节点,帮助记录路径
  28. void print_path(int s,int t) //输出从s到t之间的最短路径
  29. {
  30. if (s==t){
  31. cout<<0;
  32. return ;
  33. }
  34. print_path(s,pre[t]);
  35. cout<<t;
  36. }
  37. int dis[N]; //记录每个节点到起点之间的距离
  38. void dijkstra(){
  39. int s=1; //起始点s是1
  40. bool done[N]; //记录是否已经被标记为最短路径
  41. for (int i=1;i<=n;++i) {
  42. dis[i]=INF;
  43. done[i]=false;
  44. }
  45. dis[s]=0; //起点到自己的距离是0
  46. priority_queue<s_node>Q; //建立优先数组,存储节点信息
  47. Q.push(s_node(s,dis[s])); //放第一个节点
  48. while (!Q.empty()){
  49. s_node q=Q.top(); Q.pop(); //输出第一个节点
  50. if (done[q.id]) continue; //如果已经找到了最短路径,那么就没必要继续找了,就直接退出
  51. done[q.id]=true;
  52. //开始检查q节点的邻居节点
  53. for (int i=0;i<e[q.id].size();++i){
  54. edge y=e[q.id][i]; //表示了q这个节点的第i个邻居节点
  55. if (done[y.to]) continue; //如果这个节点已经找到了最短路径,那么就退出
  56. if (dis[y.to]> y.w+q.n_dis){
  57. dis[y.to]=y.w+q.n_dis;
  58. Q.push(s_node(y.to,dis[y.to]));
  59. pre[y.to]=q.id;
  60. }
  61. }
  62. }
  63. }
  64. signed main(){
  65. cin>>n>>m;
  66. for (int i=1;i<=n;++i) e[i].clear();
  67. while (m--){
  68. int u,v,w;
  69. cin>>u>>v>>w;
  70. e[u].push_back(edge(u,v,w));
  71. }
  72. dijkstra();
  73. for (int i=1;i<=n;++i){
  74. if (dis[i]>=INF) cout<<-1<<" ";
  75. else cout<<dis[i]<<" ";
  76. }
  77. }

榨取kkksc03https://www.luogu.com.cn/problem/P1855

输入格式

第一行三个整数 �,�,�n,M,T,表示一共有 �n(1≤�≤1001≤n≤100)个愿望, kkksc03 的手上还剩 �M(0≤�≤2000≤M≤200)元,他的暑假有 �T(0≤�≤2000≤T≤200)分钟时间。

第 22~�+1n+1 行 ��mi​ , ��ti​ 表示第 �i 个愿望所需要的金钱和时间。

输出格式

一行,一个数,表示 kkksc03 最多可以实现愿望的个数。

思路:01背包问题,就是由两个背包容量

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define lowbit(x) (x& - (x))
  4. #define int long long
  5. const int N=1e5+5;
  6. int dp[205][205],n,m,t,qian[205],tt[205];
  7. signed main() {
  8. cin>>n>>m>>t;
  9. for (int i=1;i<=n;++i){
  10. cin>>qian[i]>>tt[i];
  11. }
  12. memset(dp,0,sizeof(dp));
  13. for (int k=1;k<=n;++k){
  14. for (int i=m;i>=qian[k];--i){
  15. for (int j=t;j>=tt[k];--j){
  16. dp[i][j]=max(dp[i][j],dp[i-qian[k]][j-tt[k]]+1);
  17. }
  18. }
  19. }
  20. cout<<dp[m][t];
  21. }

吃奶酪https://www.luogu.com.cn/problem/P1433

题目描述

房间里放着 �n 块奶酪。一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在 (0,0)(0,0) 点处。

输入格式

第一行有一个整数,表示奶酪的数量 �n。

第 22 到第 (�+1)(n+1) 行,每行两个实数,第 (�+1)(i+1) 行的实数分别表示第 �i 块奶酪的横纵坐标 ��,��xi​,yi​。

输出格式

输出一行一个实数,表示要跑的最少距离,保留 22 位小数。

输入输出样例

输入 #1复制

4
1 1
1 -1
-1 1
-1 -1

输出 #1复制

7.41

说明/提示

数据规模与约定

对于全部的测试点,保证 1≤�≤151≤n≤15,∣��∣,∣��∣≤200∣xi​∣,∣yi​∣≤200,小数点后最多有 33 位数字。

提示

对于两个点 (�1,�1)(x1​,y1​),(�2,�2)(x2​,y2​),两点之间的距离公式为 (�1−�2)2+(�1−�2)2(x1​−x2​)2+(y1​−y2​)2​。

思路:状态压缩DP

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define lowbit(x) (x& - (x))
  4. const int INF=0x3f3f3f3f3f3f3f3fLL;
  5. #define int long long
  6. double dp[1<<16][20];
  7. double a[20][20];
  8. double x[20],y[20];
  9. int n;
  10. double dis(int i,int j){
  11. return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
  12. }
  13. signed main(){
  14. cin>>n;
  15. memset(dp,127,sizeof(dp));
  16. for (int i=1;i<=n;++i){
  17. cin>>x[i]>>y[i];
  18. dp[1<<(i-1)][i]=dis(i,0);
  19. }
  20. x[0]=0,y[0]=0;
  21. for (int i=0;i<n;++i){
  22. for (int j=i+1;j<=n;++j){
  23. a[i][j]=dis(i,j);
  24. a[j][i]=a[i][j];
  25. }
  26. }
  27. for (int s=1;s<(1<<n);++s){
  28. for (int i=1;i<=n;++i){
  29. if ((s&(1<<(i-1)))==0) continue;
  30. //if (s==(1<<(i-1))) dp[s][i]=dis(i,0);
  31. for (int j=1;j<=n;++j){
  32. if (i==j) continue;
  33. if ((s&(1<<(j-1)))==0) continue;
  34. dp[s][i]=min(dp[s][i],dp[s^(1<<(i-1))][j]+a[i][j]);
  35. }
  36. }
  37. }
  38. double ans=100000000.0;
  39. for (int i=1;i<=n;++i){
  40. ans=min(ans,dp[(1<<n)-1][i]);
  41. }
  42. printf("%.2lf\n",ans);
  43. }

补给https://www.luogu.com.cn/problem/solution/P8733

题目描述

小蓝是一个直升飞机驾驶员,他负责给山区的 �n 个村庄运送物资。

每个月,他都要到每个村庄至少一次,可以多于一次,将村庄需要的物资运送过去。

每个村庄都正好有一个直升机场,每两个村庄之间的路程都正好是村庄之间的直线距离。

由于直升机的油箱大小有限,小蓝单次飞行的距离不能超过 �D。每个直升机场都有加油站,可以给直升机加满油。

每个月,小蓝都是从总部出发,给各个村庄运送完物资后回到总部。如果方便,小蓝中途也可以经过总部来加油。

总部位于编号为 11 的村庄。

请问,要完成一个月的任务,小蓝至少要飞行多长距离?

输入格式

输入的第一行包含两个整数 �n,�D,分别表示村庄的数量和单次飞行的距离。

接下来 �n 行描述村庄的位置,其中第 �i 行两个整数 ��xi​,��yi​ 分别表示编号为 �i 的村庄的坐标。村庄 �i 和村庄 �j 之间的距离为 (��−��)2+(��−��)2(xi​−xj​)2+(yi​−yj​)2​。

输出格式

输出一行,包含一个实数,四舍五入保留正好 22 位小数,表示答案。

输入输出样例

输入 #1复制

4 6
1 1
4 5
8 5
11 1

输出 #1复制

28.00

说明/提示

对于所有数据,保证,1≤�≤20,1≤��,��≤104,1≤�≤1051≤n≤20,1≤xi​,yi​≤104,1≤D≤105。

思路:floyd找到最短路径,然后状压DP

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define lowbit(x) (x& - (x))
  4. #define int long long
  5. const int N=1e5+5;
  6. double dp[1<<20][25],a[25][25];
  7. int n,d;
  8. double x[21],y[21];
  9. double dis(int i,int j){
  10. return sqrt(((x[i]-x[j])*(x[i]-x[j]))+((y[i]-y[j])*(y[i]-y[j])));
  11. }
  12. void floyd(){
  13. for (int k=1;k<=n;++k){
  14. for (int i=1;i<=n;++i){
  15. for (int j=1;j<=n;++j){
  16. a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
  17. }
  18. }
  19. }
  20. }
  21. signed main() {
  22. cin>>n>>d;
  23. for (int i=1;i<=n;++i){
  24. cin>>x[i]>>y[i];
  25. }
  26. for (int i=1;i<=n;++i){
  27. for (int j=1;j<=n;++j){
  28. if (dis(i,j)>d){
  29. a[i][j]=1e10;
  30. }
  31. else {
  32. a[i][j]=dis(i,j);
  33. }
  34. }
  35. }
  36. floyd();
  37. for(int i=0;i<(1<<n);++i){
  38. for(int j=1;j<=n;++j){
  39. dp[i][j]=1e10;
  40. }
  41. }
  42. dp[1][1]=0;
  43. for (int s=0;s<(1<<n);++s){
  44. for (int j=1;j<=n;++j){
  45. if ((s&(1<<(j-1)))==0) continue;
  46. for (int k=1;k<=n;++k){
  47. if (j==k)continue;
  48. if ((s&(1<<(k-1)))==0) continue;
  49. dp[s][j]=min(dp[s][j],dp[s^(1<<(j-1))][k]+a[k][j]);
  50. }
  51. }
  52. }
  53. double res=1e13;
  54. for (int i=1;i<=n;++i){
  55. res=min(res,dp[(1<<n)-1][i]+a[i][1]);
  56. }
  57. printf("%.2lf",res);
  58. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/70953
推荐阅读
相关标签
  

闽ICP备14008679号