题目描述 在ICPC程序设计大赛期间,小P作为志愿者的任务是给各个学校送盒饭,小P一次最多可以携带M份盒饭。总共有N个学校来参加比赛,这N个学校的休息点在一条笔直的马路边一字排开,路的一头是小P取盒饭的地方,假设为原点,每两个相邻点之间,小明需要行走15秒,包括从原点到第一个休息点,交付一份盒饭需要3秒时间。从第一个休息点到第N个休息点需要的盒饭数分别为 a1, a2, a3..., an。 问小P最短需要多少时间把全部盒饭送完并回到原点。 输入 第一行输入一个正整数T,表示有T组测试数据,每组占两行,第一行两个整数M、N(0<M,N<50),第二行输入N个整数a1 a2 a3 ...an (0<=a1....an<50) 输出 每行输出一个整数,对应一组测试数据,表示小P送完全部盒饭并返回原点的总时间(秒)。 样例输入 Copy 2 18 2 8 6 10 3 5 0 8 样例输出 Copy 102 159 提示 消耗的时间最少只由走的路程最短决定,每一趟来回走的路程是这一次送餐的最远的点距离原点的两倍。
我的错误:

//M份盒饭。 总共有N个学校来参加比赛 //每两个相邻点之间,小明需要行走15秒 //交付一份盒饭需要3秒时间 //102=15*(n*2)+(A1+A2+An)*3 //a1 a2 a3 a4 #include<iostream> using namespace std; int main() { int t,n,sum=0,book,a,b,i,j;//book表示手里拿的东西 t表示时间 cin>>n;//几组数据 while(n--){ cin>>a>>b; int arr[b]; book=a; t=0; sum=0; for( i=0;i<b;i++) { cin>>arr[i]; sum+=arr[i];} for(j=b-1;j>=0;j--){ book=book-arr[j]; while(book<=0){ if(i==0&&book==0) break; t+=(j+1)*15*2; book=book+a; } } t=t+b*15*2+sum*3; cout<<t<<endl; } }
错误分析主要是送最远的饭的目标寻找没考虑,考虑后正确

//M份盒饭。 总共有N个学校来参加比赛 //每两个相邻点之间,小明需要行走15秒 //交付一份盒饭需要3秒时间 //102=15*(n*2)+(A1+A2+An)*3 //a1 a2 a3 a4 #include<iostream> using namespace std; int main() { int t,n,sum=0,book,a,b,i,j,q;//book表示手里拿的东西 t表示时间 cin>>n;//几组数据 while(n--){ cin>>a>>b; int arr[b]; book=a; t=0; sum=0; for( i=0;i<b;i++) { cin>>arr[i]; sum+=arr[i]; if(arr[i]>0) q=i; } for(j=q;j>=0;j--){ book=book-arr[j]; while(book<0){ t+=(j+1)*15*2; book=book+a; } } t=t+(q+1)*15*2+sum*3; cout<<t<<endl; } }
同学用的贪心算法:

#include <stdio.h> #include <bits/stdc++.h> using namespace std; typedef long long ll; const int INF = 0x3f3f3f3f; const ll LINF = 0x3f3f3f3f3f3f3f3f; const int N = 100; int a[N]; int main() { #ifdef LOCAL freopen("C:/input.txt", "r", stdin); #endif int T; cin >> T; while (T--) { int m, n, p = 0; //p最后一个有效点 scanf("%d%d", &m, &n); ll ans = 0; for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); if (a[i]) p = i; } while (p) { ans += p * 30; //到p再回原点代价 int t = m; //身上所带物品 while (p && t) { int e = min(t, a[p]); //交付 t -= e; a[p] -= e; ans += e * 3; //交付代价 while (p && !a[p]) //如果当前点已经送完则移动p p--; } } printf("%lld ", ans); } return 0; }
分析:
1.从远往近送,
2.确定的最远点需要送餐,arr[i]>0
3.贪心问题,e=min(arr[j],book),很重要
自己实现,差不多,

//M份盒饭。 总共有N个学校来参加比赛 //每两个相邻点之间,小明需要行走15秒 //交付一份盒饭需要3秒时间 //102=15*(n*2)+(A1+A2+An)*3 //a1 a2 a3 a4 #include<iostream> using namespace std; int main() { int t,n,sum=0,book,a,b,i,j,p,e;//book表示手里拿的东西 t表示时间 cin>>n;//几组数据 while(n--){ cin>>a>>b; int arr[b]; book=a; t=0; sum=0; for( i=0;i<b;i++) { cin>>arr[i]; sum+=arr[i]; if(arr[i]) p=i; } for(j=p;j>=0;j--){ e=min(arr[j],book); book-=e; arr[j]-=e; while(arr[j]>0){ t+=(j+1)*15*2; book=a; e=min(arr[j],book); book-=e; arr[j]-=e; } } t=t+(p+1)*15*2+sum*3; cout<<t<<endl; } }