洛谷 P3040 [USACO12JAN]贝尔分享Bale Share
P3040 [USACO12JAN]贝尔分享Bale Share
题目描述
Farmer John has just received a new shipment of N (1 <= N <= 20) bales of hay, where bale i has size S_i (1 <= S_i <= 100). He wants to divide the bales between his three barns as fairly as possible.
After some careful thought, FJ decides that a "fair" division of the hay bales should make the largest share as small as possible. That is, if B_1, B_2, and B_3 are the total sizes of all the bales placed in barns 1, 2, and 3, respectively (where B_1 >= B_2 >= B_3), then FJ wants to make B_1 as small as possible.
For example, if there are 8 bales in these sizes:
2 4 5 8 9 14 15 20
A fair solution is
Barn 1: 2 9 15 B_1 = 26
Barn 2: 4 8 14 B_2 = 26
Barn 3: 5 20 B_3 = 25
Please help FJ determine the value of B_1 for a fair division of the hay bales.
FJ有N (1 <= N <= 20)包干草,干草i的重量是 S_i (1 <= S_i <= 100),他想尽可能平均地将干草分给3个农场。
他希望分配后的干草重量最大值尽可能地小,比如, B_1,B_2和 B_3是分配后的三个值,假设B_1 >= B_2 >= B_3,则他希望B_1的值尽可能地小。
例如:8包干草的重量分别是:2 4 5 8 9 14 15 20,一种满足要求的分配方案是
农场 1: 2 9 15 B_1 = 26
农场 2: 4 8 14 B_2 = 26
农场 3: 5 20 B_3 = 25
请帮助FJ计算B_1的值。
输入输出格式
输入格式:
-
Line 1: The number of bales, N.
- Lines 2..1+N: Line i+1 contains S_i, the size of the ith bale.
输出格式:
- Line 1: Please output the value of B_1 in a fair division of the hay bales.
输入输出样例
8
14
2
5
15
8
9
20
4
26
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 30 using namespace std; int n; int A,B,C; int ans=0x7f7f7f7fl; int sum[MAXN]; void dfs(int now){ if(max(A,max(B,C))>ans) return ; if(now==n+1){ ans=max(A,max(C,B)); return; } A+=sum[now];dfs(now+1);A-=sum[now]; B+=sum[now];dfs(now+1);B-=sum[now]; C+=sum[now];dfs(now+1);C-=sum[now]; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&sum[i]); dfs(1); cout<<ans; }
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 30 using namespace std; int n; int A,B,C; int ans=0x7f7f7f7fl; int sum[MAXN]; void dfs(int now){ if(now==n+1){ ans=max(A,max(C,B)); return; } A+=sum[now];if(A<ans) dfs(now+1);A-=sum[now]; B+=sum[now];if(B<ans) dfs(now+1);B-=sum[now]; C+=sum[now];if(C<ans) dfs(now+1);C-=sum[now]; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&sum[i]); dfs(1); cout<<ans; }
正解思路:动态规划。
f[i][j][k]表示到第i堆干草为止,第一个农场分到j的干草,第二个农场分到k的干草。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 10010 using namespace std; int n; int dp[23][2010][2010]; int num[MAXN],sum[MAXN]; int dfs(int now,int x,int y){ int z=sum[now-1]-x-y; if(now==n+1) return max(x,max(y,z)); if(dp[now][x][y]) return dp[now][x][y]; dp[now][x][y]=min(dfs(now+1,x+num[now],y),min(dfs(now+1,x,y+num[now]),dfs(now+1,x,y))); return dp[now][x][y]; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&num[i]); for(int i=1;i<=n;i++) sum[i]=sum[i-1]+num[i]; dfs(1,0,0); cout<<dp[1][0][0]; }