http://codeforces.com/gym/101492/problem/E
思路:
按过河时间排序后
有两种最优策略:
1.最轻的带最重的过去,
2.两个最轻的带两个最重的过去。
每次判断两人,比较两种策略哪个更优。
样例1:编号为1,2,3,首先1和3先过去,1回来,然后1和2过去,时间是50+30+40=120
样例2:编号为1,2,3,4,首先1和2先过去,1回来,然后3和4过去,2回来,最后1和2过去,时间是20+10+100+20+20=170
题目分析:这题看起来似乎是dp的题目,但是看内存和时间,2个循环的时间并不足够。但是稍微分析,其实可以发现,有两种情况:
假设有编号为1,2,3,4,4个人在A要去B;
第一种情况:先1+2过去,然后换3+4过去;具体流程是1+2过去,1回来,3+4过去,2回来,此时时间是t1=num[2]+num[1]+num[4]+num[2]=num[2]*2+num[1]+num[4];
第二种情况:1+4过去,1回来,1+3过去,1回来;也就是通过1来回,逐个过去。时间是t2=num[4]+num[1]+num[3]+num[1]=num[1]*2+num[3]+num[4];
由上两种情况,总结出选择哪一种过法,可以比较t1和t2的时间取小,也就是看num[2]+num[2]>num[1]+num[3]?t1:t2
#include <cmath> #include <algorithm> #include <iostream> #include <algorithm> #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdio.h> #include <set> #include <stack> #include <string.h> #include <vector> #include <queue> #define ME(x , y) memset(x , y , sizeof(x)) #define SF(n) scanf("%d" , &n) #define rep(i , n) for(int i = 0 ; i < n ; i ++) #define INF 0x3f3f3f3f using namespace std; long long a[100009]; int main() { int n ; while(scanf("%d" , &n) != EOF) { for(int i = 0 ; i < n ; i++) { scanf("%lld" , &a[i]); } sort(a , a + n); long long ans = 0 ; if(n == 1) { ans = a[0]; } else { if(n % 2 == 1) { ans += a[0] + a[1] + a[2]; for(int i = 4 ; i < n ; i += 2) { ans += min(2 *a[0] + a[i-1] + a[i] , a[0] + 2*a[1] + a[i]); } } else { ans += a[1]; for(int i = 3 ; i < n ; i += 2 ) { ans += min(2*a[0] + a[i-1] + a[i] , a[0] + 2*a[1] + a[i]); } } } printf("%lld " , ans); } return 0 ; }
http://poj.org/problem?id=2573
另外需要输出具体过程
//#include <bits/stdc++.h> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> #include <string> #include <stdio.h> #include <queue> #include <stack> #include <map> #include <set> #include <string.h> #include <vector> #define ME(x , y) memset(x , y , sizeof(x)) #define SF(n) scanf("%d" , &n) #define rep(i , n) for(int i = 0 ; i < n ; i ++) #define INF 0x3f3f3f3f #define mod 20191117 #define PI acos(-1) using namespace std; typedef long long ll ; int a[1009]; vector<int>v[100009]; int main() { int n ; scanf("%d" , &n); for(int i = 1 ; i <= n ; i++) { scanf("%d" , &a[i]); } if(n == 1){ cout << a[1] << endl; cout << a[1] << endl; return 0 ; } sort(a + 1 , a + n + 1); int ans = 0 , j , sum = 0; for(j = n ; j >= 4 ; j -= 2) { if(a[j]+a[j-1]+2*a[1] >= a[j]+a[1]+2*a[2]) { sum += a[j]+a[1]+2*a[2] ; v[++ans].push_back(a[1]),v[ans].push_back(a[2]); v[++ans].push_back(a[1]); v[++ans].push_back(a[j-1]), v[ans].push_back(a[j]); v[++ans].push_back(a[2]); } else{ sum += a[j]+a[j-1]+2*a[1] ; v[++ans].push_back(a[1]) , v[ans].push_back(a[j]); v[++ans].push_back(a[1]); v[++ans].push_back(a[1]), v[ans].push_back(a[j-1]); v[++ans].push_back(a[1]); } } if(j == 2) { sum += a[2] ; v[++ans].push_back(a[1]) , v[ans].push_back(a[2]); } else{ sum += a[1] + a[2] + a[3]; v[++ans].push_back(a[1]) , v[ans].push_back(a[3]); v[++ans].push_back(a[1]); v[++ans].push_back(a[1]) , v[ans].push_back(a[2]); } cout << sum << endl ; for(int i = 1 ; i <= ans ; i++) { if(v[i].size() == 2) { cout << v[i][0] << " " << v[i][1] << endl; } else{ cout << v[i][0] << endl ; } } return 0; }