贪心(国王游戏,机器人)

国王游戏

贪心地推出一个结论就好,证明很easy (直接将所有大臣按左右手上的数的乘积从小到大排序,得到的序列就是最优排队方案)

代码:

#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

typedef pair<int, int> PII;
const int N = 1010;

int n;
PII p[N];

vector<int> mul(vector<int>a, int b)
{
    vector<int> c;
    int t = 0;
    for (int i = 0; i < a.size(); i ++ )
    {
        t += a[i] * b;
        c.push_back(t % 10);
        t /= 10;
    }
    while (t)
    {
        c.push_back(t % 10);
        t /= 10;
    }
    return c;
}

vector<int> div(vector<int>a, int b)
{
    vector<int> c;
    //标记,不放前导0
    bool is_first = true;
    for (int i = a.size() - 1, t = 0; i >= 0; i -- )
    {
        t = t * 10 + a[i];
        int x = t / b;
        if (!is_first || x)
        {
            is_first = false;
            c.push_back(x);
        }
        t %= b;
    }
    reverse(c.begin(), c.end());
    return c;
}

vector<int> max_vec(vector<int> a, vector<int> b)
{
    if (a.size() > b.size()) return a;
    if (a.size() < b.size()) return b;
    //vector存的是小位在前,高位在后,所以要倒过来判断
    if (vector<int>(a.rbegin(), a.rend()) > vector<int>(b.rbegin(), b.rend())) return a;
    return b;
}

int main()
{
    cin >> n;
    for (int i = 0; i <= n; i ++ )
    {
        int a, b;
        cin >> a >> b;
        p[i] = {a * b, a};
    }
    sort(p + 1, p + n + 1);

    vector<int> product(1, 1);

    vector<int> res(1, 0);
    for (int i = 0; i <= n; i ++ )
    {
        if (i) res = max_vec(res, div(product, p[i].first / p[i].second));
        product = mul(product, p[i].second);
    }

    for (int i = res.size() - 1; i >= 0; i -- ) cout << res[i];
    cout << endl;

    return 0;
}

机器人:
在这里插入图片描述
思路:
在这里插入图片描述

代码1(贪心+__int128):

注意: __int128要一位一位的读入 , 一位一位的输出

#include <bits/stdc++.h>
#define lll __int128
using namespace std;
struct T{
    int x,y;
}c[22];
bool cmp(T &a,T &b){return a.x*b.y+a.y<b.x*a.y+b.y;}
void print(lll x){
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
signed main()
{
    ios::sync_with_stdio(0),cin.tie(0);
    int n,x;
    cin>>n>>x;
    lll res=x;
    for(int i=0;i<n;++i) cin>>c[i].x>>c[i].y;
    sort(c,c+n,cmp);
    for(int i=0;i<n;++i) res = res*c[i].x+c[i].y;
    print(res);
    return 0;
}

代码2(贪心+大数板子):

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstring>
#include <set>
#include <map>
#include <sstream>
#define pb push_back
#define debug(x) cout<<#x<<":"<<x<<endl;
#define f(i,a,n) for(int i=a;i<n;++i)
#define ff(i,a,n) for(int i=a;i<=n;++i)
using namespace std;
typedef long long ll;
typedef double dbl;
typedef pair<int, int> pi;
const int INF = 0x3f3f3f3f;
inline ll in() { char ch = getchar();ll x = 0, f = 1;while (ch<'0' || ch>'9') { if (ch == '-')f = -1;ch = getchar(); }while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - '0';ch = getchar(); }return x * f; }
inline int lowbit(int x) { return x&(-x);}
ll qpow(ll a, ll n, ll m) { ll s = 1;while (n) { if (n & 1) { s = s * a % m; }a = (a*a) % m;n = n / 2; }return s; }
void ex_gcd(ll a, ll b, ll &x, ll &y, ll &d) { if (!b) { d = a, x = 1, y = 0; } else { ex_gcd(b, a % b, y, x, d);y -= x * (a / b); } }
ll inv(ll t, ll p) { ll d, x, y;ex_gcd(t, p, x, y, d);return d == 1 ? (x % p + p) % p : -1; }
bool isPrime(ll x) { if (x == 2)return true;if (x % 2 == 0)return false;for (ll i = 2;i*i <= x;i++) if (x % i == 0)return false; return true; }
inline ll inv2(ll x,ll p) { return qpow(x,p-2,p);}
ll gcd(ll a, ll b) { return b ? gcd(b, a%b) : a; }
ll lcm(ll a, ll b) { return 1LL*a/gcd(a,b)*b;}
int dx[4]={0,0,-1,1},dy[4]={1,-1,0,0};
struct f{
    ll a,b;
}c[22];
bool cmp(f t1,f t2){
    return t2.a*t1.b-t1.a*t2.b > t1.b-t2.b;
}

vector<int> add(vector<int> &A, vector<int> &B){
    if (A.size() < B.size()) return add(B, A);
    vector<int> C;
    int t = 0;
    for (int i = 0; i < A.size(); i ++ ){
        t += A[i];
        if (i < B.size()) t += B[i];
        C.push_back(t % 10);
        t /= 10;
    }
    if (t) C.push_back(t);
    return C;
}

vector <int> mul(vector <int> & A, int b) {
    vector <int> C;
    int t = 0;
    for (int i = 0; i < A.size(); i ++) {
        t += A[i] * b;       // t + A[i] * b = 7218
        C.push_back(t % 10); // 只取个位 8
        t /= 10;             // 721 看作 进位
    }
    while (t) {// 处理最后剩余的 t
        C.push_back(t % 10);
        t /= 10;
    }
    while (C.size() > 1 && C.back() == 0) C.pop_back();//12345*0 != 00000
    return C;
}

void solve(){
    ll n,x;
    cin>>n>>x;
    f(i,0,n)c[i].a=in(),c[i].b=in();
    sort(c,c+n,cmp);
    vector<int>res;
    while(x){res.pb(x%10);x/=10;}
    f(i,0,n){
        res=mul(res,c[i].a);
        vector<int>tem;
        while(c[i].b){
            tem.pb(c[i].b%10);c[i].b/=10;
        }
        res=add(res,tem);
    }
    for(int i=res.size()-1;i>=0;i--)
        cout<<res[i];
}
int main(){
    int T=1;
    while(T--) {
        solve();
    }
    return 0;
}

代码3(状压+记忆化dp):

思路:

f [ s t ] f[st] f[st]表示已经经过了 s t st st状态的机器人时,最大的得分是多少
f [ s t ] = m a x ( f [ s t 0 ] ∗ a j + b j ) f[st]=max(f[st_{0}]*a_{j}+b_{j}) f[st]=max(f[st0]aj+bj)
s t 0 st_{0} st0中第 j j j为为 0 0 0,即第 j j j个机器人还没有用
s t st st中第 j j j位为 1 1 1,其他位与 s t 0 st_{0} st0相同

#include <bits/stdc++.h>
using namespace std;
int n, x;
int a[30], b[30];
__int128  f[(1<<20)+100];
__int128 dp(int st)
{
    if (f[st] != 0) return f[st];
    for (int i = 0; i < n; i++)
    {
        //如果st里面包含第i个机器人
        if ((st & (1 << i)) != 0)
        {
            //单独把第i位从1变为0,其他位不变
            int t = st ^ (1 << i);
            f[st] = max(f[st], dp(t)*a[i+1] + b[i+1]);
        }
    }
    return f[st];
}
inline void print(__int128 x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
int main()
{
    scanf("%d%d", &n, &x);
    for (int i = 1; i <= n; i++)
        scanf("%d%d", &a[i], &b[i]);
    f[0] = x;
    print(dp((1<<n)-1));
    return 0;
}

代码4(状压+dp):

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pb push_back
#define fir first
#define sec second
#define rep(i, l, r) for (int i = l; i <= r; i++)
#define per(i, l, r) for (int i = l; i >= r; i--)
#define mset(s, t) memset(s, t, sizeof(s))
#define mcpy(s, t) memcpy(s, t, sizeof(t))
//ckmax:把两者的较大值赋给前面
template<typename T1, typename T2> void ckmax(T1 &a, T2 b) { if (a < b) a = b; }
int read() {
    int x = 0, f = 0; char ch = getchar();
    while (!isdigit(ch)) f |= ch == '-', ch = getchar();
    while (isdigit(ch)) x = 10 * x + ch - '0', ch = getchar();
    return f ? -x : x;
}
template<typename T> void print(T x) {
    if (x < 0) putchar('-'), x = -x;
    if (x >= 10) print(x / 10);
    putchar(x % 10 + '0');
}
template<typename T> void print(T x, char let) {
    print(x), putchar(let);
}
//lowbit:二进制最低位的1与后边的0组成的数
int lowbit(int t){
    return t&(-t);
}
const int N = 20;
__int128 dp[1 << N];
int a[N], b[N], bit[1 << N], n, x;
int main() {
    cin >> n >> x;
    for (int i = 0; i < n; i++) cin >> a[i] >> b[i];
    for (int i = 0; i < n; i++) bit[1 << i] = i;
    dp[0] = x;
    int all = (1 << n) - 1;
    for (int st = 0; st <= all; st++) {
        int t = all ^ st;//st里面1变0,0变1
        while (t) {
            int y = bit[lowbit(t)];
            t ^= 1 << y;
            ckmax(dp[st | 1 << y], dp[st] * a[y] + b[y]);
        }
    }
    print(dp[all]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值