【问题描述】
恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右 手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 n 位大臣排 成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每 位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右 手上的数,然后向下取整得到的结果。 国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序, 使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。
【输入】
输入文件为 game.in。
第一行包含一个整数 n,表示大臣的人数。 第二行包含两个整数 a和b,之间用一个空格隔开,分别表示国王左手和右手上的整数。
接下来 n 行,每行包含两个整数 a 和 b,之间用一个空格隔开,分别表示每个大臣左手 和右手上的整数。
【输出】
输出文件名为 game.out。
输出只有一行,包含一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。
【输入输出样例】
game.in
3
1 1
2 3
7 4
4 6
game.out
2
【输入输出样例说明】
按 1、2、3 号大臣这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;
按 1、3、2 这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;
按 2、1、3 这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;
按 2、3、1 这样排列队伍,获得奖赏最多的大臣所获得金币数为 9;
按 3、1、2 这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;
按 3、2、1 这样排列队伍,获得奖赏最多的大臣所获得金币数为 9。
因此,奖赏最多的大臣最少获得 2 个金币,答案输出 2。
【数据范围】 对于 20%的数据,有 1≤ n≤ 10,0 < a、b < 8;
对于 40%的数据,有 1≤ n≤20,0 < a、b < 8;
对于 60%的数据,有 1≤ n≤100; 对于 60%的数据,保证答案不超过 109;
对于 100%的数据,有 1 ≤ n ≤1,000,0 < a、b < 10000。
思路:
非要证明的话还是挺抽象的,比较难理解,但举反例就很 clear .
1. 如果一个大臣,左手的数字非常大,要满足国王,我们就要尽可能地把他往后放,让他左手数字的作用发挥的最小
2. 如果一个大臣,右手的数字非常大,要满足国王,我们也要把他尽可能地往后放,让他右手的数字发挥的作用最大
所以呢,左手右手其实是互相成正比的,就设 f[i] = l[i]*r[i]
以 f[i] 排升序,就是一个最优的队列(之一)
20分的全排列
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; struct P{ int l,r; }d[1001]; int n,ans=0x3f3f3f3f,a[1001],pre[1001]; bool vis[1001]; void dfs(int x) { if(x>n) { int t=0; for(int i=1;i<=n;++i) t=max(pre[i-1]/d[a[i]].r,t); ans=min(ans,t); return ; } for(int i=1;i<=n;++i) { if(vis[i]) continue; vis[i]=1; a[x]=i; pre[i]=pre[i-1]*d[i].l; dfs(x+1); vis[i]=0; } } int main() { // freopen("game.in","r",stdin),freopen("game.out","w",stdout); scanf("%d",&n); for(int i=0;i<=n;++i) scanf("%d%d",&d[i].l,&d[i].r); memset(pre,0,sizeof(pre)); pre[0]=d[0].l; dfs(1); printf("%d",ans); return 0; }
60分的无高精度
#include<stdio.h> #include<algorithm> using namespace std; int n; long long t,pre,ans; struct node { int l,r,f; }a[1001]; bool cmp(node a,node b){ return a.f<b.f; } int main() { scanf("%d",&n); scanf("%d%lld",&pre,&t); for(int i=1;i<=n;++i) { scanf("%d%d",&a[i].l,&a[i].r); a[i].f=a[i].l*a[i].r; } sort(a+1,a+1+n,cmp); for(int i=1;i<=n;++i) { t=(long long)pre/a[i].r; if(t) ans=max(ans,t); pre*=a[i].l; } printf("%lld",ans); return 0; }
AC高精度
#include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <iostream> #include <vector> #include <algorithm> using namespace std; struct node { int l,r,f; }a[1001]; bool cmp(node a,node b){ return a.f<b.f; } struct BigInt { vector<int> v; static const int BASE = 10000; static const int WIDTH = 4; BigInt(long long x) { do { v.push_back(x % BASE); }while (x /= BASE); } BigInt(string str) { int size = str.length(); v.reserve(size); for(int i = size - 1; i >= 0; i-=WIDTH){ string sub; if(i-WIDTH + 1<0)sub = str.substr(0,i+1); else sub = str.substr(i - WIDTH +1,WIDTH); int temp = atoi(sub.c_str()); v.push_back(temp); } } BigInt() { } void removePreZero() { while(v.size() >= 1 && v.back() == 0) v.pop_back(); } bool operator<(const BigInt &a) const { if (v.size() != a.v.size()) { return v.size() < a.v.size(); } for (int i = v.size() - 1; i >= 0; i--) { if (v[i] != a.v[i]) { return v[i] < a.v[i]; } } return false; } bool operator>(const BigInt &a) const {return a < *this;} bool operator<=(const BigInt &a) const {return !(a < *this);} bool operator>=(const BigInt &a) const {return !(*this < a);} bool operator!=(const BigInt &a) const {return a < *this || a > *this;} bool operator==(const BigInt &a) const {return !(a < *this) && !(a > *this);} BigInt operator+(const BigInt &a) const { BigInt ans; ans.v.reserve(max(a.v.size(), v.size())); int sum = 0; for (int i = 0; i < max(a.v.size(), v.size()); i++) { if (i < a.v.size()) sum += a.v[i]; if (i < v.size()) sum += v[i]; ans.v.push_back(sum % BASE); sum /= BASE; } if (sum) ans.v.push_back(sum); ans.removePreZero(); return ans; } /* BigInt operator+=(const BigInt &a) const { return *this = *this + a; }*/ BigInt operator-(const BigInt &a) const { BigInt ans; ans.v.reserve(max(a.v.size(), v.size())); int dif = 0; for (int i = 0; i < max(a.v.size(), v.size()); i++) { if (i < v.size()) dif += v[i]; if (i < a.v.size()) dif -= a.v[i]; if (dif >= 0) { ans.v.push_back(dif); dif = 0; } else { ans.v.push_back((dif +BASE) % BASE); dif = -1; } } ans.removePreZero(); return ans; } /* BigInt operator-=(const BigInt &a) const { return *this = *this - a; }*/ BigInt operator*(const BigInt &a) const { BigInt ans; ans.v.resize(v.size() + a.v.size(), 0); for (int i = 0; i < v.size(); i++) { for (int j = 0; j < a.v.size(); j++) { ans.v[i + j] += v[i] * a.v[j]; ans.v[i + j + 1] += ans.v[i + j] / BASE; ans.v[i + j] %= BASE; } } ans.removePreZero(); return ans; } /* BigInt operator*=(const BigInt &a) const { return *this = *this * a; }*/ BigInt operator/(const BigInt &a) const { BigInt ans, ret(0); ans.v.resize(v.size(), 0); // ret = 0; for (int i = v.size() - 1; i >= 0; i--) { ret = ret * BASE + v[i]; while (ret >= a) { ret = ret - a; ans.v[i]++; } } ans.removePreZero(); return ans; } BigInt operator/(const int &a) const { BigInt ans; ans.v.resize(v.size(), 0); int ret = 0; for (int i = v.size() - 1; i >= 0; i--) { ret += v[i]; if(ret >= a){ ans.v[i] += ret/a; ret%=a; } ret*=BASE; } ans.removePreZero(); return ans; } void print(){ if(v.size()==0)printf("0"); for(int i = v.size() - 1 ; i >= 0 ; i--){ if(i!=v.size()-1){ if(v[i]<10)printf("000"); else if(v[i]<100)printf("00"); else if(v[i]<1000)printf("0"); } printf("%d",v[i]); } } /* BigInt operator/=(const BigInt &a) const { return *this = *this / a; }*/ }ans,pre,t; int n,temp,t1,t2; int main() { scanf("%d",&n); scanf("%d%d",&t1,&t2); pre=t1; for(int i=1;i<=n;++i) { scanf("%d%d",&a[i].l,&a[i].r); a[i].f=a[i].l*a[i].r; } sort(a+1,a+1+n,cmp); for(int i=1;i<=n;++i) { t=pre/a[i].r; if(t>ans) ans=t; pre=pre*a[i].l; } ans.print(); return 0; }