矩阵取数游戏【dp+高精度】【codevs】【黄金题】

矩阵取数游戏

高精度是套用的一个模板。

#include <algorithm> // max
#include <cassert>   // assert
#include <cstdio>    // printf,sprintf
#include <cstring>   // strlen
#include <iostream>  // cin,cout
#include <string>    // string类
#include <vector>    // vector类
using namespace std;

struct BigInteger {
    typedef unsigned long long LL;

    static const int BASE = 100000000;
    static const int WIDTH = 8;
    vector<int> s;

    BigInteger& clean(){while(!s.back()&&s.size()>1)s.pop_back(); return *this;}
    BigInteger(LL num = 0) {*this = num;}
    BigInteger(string s) {*this = s;}
   BigInteger& operator = (long long num) {      							
        s.clear();
        do {
            s.push_back(num % BASE);
            num /= BASE;
        } while (num > 0);
        return *this;
    }
    BigInteger& operator = (const string& str) {
        s.clear();
        int x, len = (str.length() - 1) / WIDTH + 1;
        for (int i = 0; i < len; i++) {
            int end = str.length() - i*WIDTH;
            int start = max(0, end - WIDTH);
            sscanf(str.substr(start,end-start).c_str(), "%d", &x);
            s.push_back(x);
        }
        return (*this).clean();
    }

    BigInteger operator + (const BigInteger& b) const {
        BigInteger c; c.s.clear();
        for (int i = 0, g = 0; ; i++) {
            if (g == 0 && i >= s.size() && i >= b.s.size()) break;
            int x = g;
            if (i < s.size()) x += s[i];
            if (i < b.s.size()) x += b.s[i];
            c.s.push_back(x % BASE);
            g = x / BASE;
        }
        return c;
    }
    BigInteger operator - (const BigInteger& b) const {
        assert(b <= *this); // 减数不能大于被减数
        BigInteger c; c.s.clear();
        for (int i = 0, g = 0; ; i++) {
            if (g == 0 && i >= s.size() && i >= b.s.size()) break;
            int x = s[i] + g;
            if (i < b.s.size()) x -= b.s[i];
            if (x < 0) {g = -1; x += BASE;} else g = 0;
            c.s.push_back(x);
        }
        return c.clean();
    }
    BigInteger operator * (const BigInteger& b) const {
        int i, j; LL g;
        vector<LL> v(s.size()+b.s.size(), 0);
        BigInteger c; c.s.clear();
        for(i=0;i<s.size();i++) for(j=0;j<b.s.size();j++) v[i+j]+=LL(s[i])*b.s[j];
        for (i = 0, g = 0; ; i++) {
            if (g ==0 && i >= v.size()) break;
            LL x = v[i] + g;
            c.s.push_back(x % BASE);
            g = x / BASE;
        }
        return c.clean();
    }
    BigInteger operator / (const BigInteger& b) const {
        assert(b > 0);  // 除数必须大于0
        BigInteger c = *this;       // 商:主要是让c.s和(*this).s的vector一样大
        BigInteger m;               // 余数:初始化为0
        for (int i = s.size()-1; i >= 0; i--) {
            m = m*BASE + s[i];
            c.s[i] = bsearch(b, m);
			m -= b*c.s[i];
        }
        return c.clean();
    }
    BigInteger operator % (const BigInteger& b) const { //方法与除法相同
        BigInteger c = *this;
        BigInteger m;
        for (int i = s.size()-1; i >= 0; i--) {
            m = m*BASE + s[i];
            c.s[i] = bsearch(b, m);
            m -= b*c.s[i];
        }
        return m;
    }
    // 二分法找出满足bx<=m的最大的x
    int bsearch(const BigInteger& b, const BigInteger& m) const{
        int L = 0, R = BASE-1, x;
        while (1) {
            x = (L+R)>>1;
            if (b*x<=m) {if (b*(x+1)>m) return x; else L = x;}
            else R = x;
        }
    }
    BigInteger& operator += (const BigInteger& b) {*this = *this + b; return *this;}
    BigInteger& operator -= (const BigInteger& b) {*this = *this - b; return *this;}
    BigInteger& operator *= (const BigInteger& b) {*this = *this * b; return *this;}
    BigInteger& operator /= (const BigInteger& b) {*this = *this / b; return *this;}
    BigInteger& operator %= (const BigInteger& b) {*this = *this % b; return *this;}

    bool operator < (const BigInteger& b) const {
        if (s.size() != b.s.size()) return s.size() < b.s.size();
        for (int i = s.size()-1; i >= 0; i--)
            if (s[i] != b.s[i]) return s[i] < b.s[i];
        return false;
    }
    bool operator >(const BigInteger& b) const{return b < *this;}
    bool operator<=(const BigInteger& b) const{return !(b < *this);}
    bool operator>=(const BigInteger& b) const{return !(*this < b);}
    bool operator!=(const BigInteger& b) const{return b < *this || *this < b;}
    bool operator==(const BigInteger& b) const{return !(b < *this) && !(b > *this);}
};

 ostream& operator << (ostream& out, const BigInteger& x) {
    out << x.s.back();
    for (int i = x.s.size()-2; i >= 0; i--) {
        char buf[20];
        sprintf(buf, "%08d", x.s[i]);
        for (int j = 0; j < strlen(buf); j++) out << buf[j];
    }
    return out;
}

 istream& operator >> (istream& in, BigInteger& x) {
    string s;
    if (!(in >> s)) return in;
    x = s;
    return in;
}
const int maxn=105;
#define ll BigInteger  

int n,m;
int a[maxn];
ll dp[maxn][maxn]; 
ll ans=0;


int main(){
	cin>>n>>m;
	for(int i=0;i<n;i++){
		
		for(int j=0;j<m;j++){
			cin>>a[j];
		}
		for(int x=0;x<m;x++){
			for(int y=0;y<m;y++){
				dp[x][y]=0;
			} 
		}
		
		ll mi=1;
		for(int j=0;j<m;j++)mi*=2;
		
		for(int j=0;j<m;j++){
			dp[j][j]=mi*a[j];
		}
		for(int len=2;len<=m;len++){	
			mi/=2;//chu2		
			for(int j=0;j<=m-len;j++){//遍历每一个大小为len的区间 
				dp[j][j+len-1]=max(dp[j+1][j+len-1]+mi*a[j],dp[j][j+len-2]+mi*a[j+len-1]);
			} 
		}
		ans+=dp[0][m-1];
	}
	
	cout<<ans<<endl;	
	return 0; 
} 

另外,我看了一下别人的代码。

以下是我喜欢的一个风格。

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int MAXN = 80 + 1;
const int MAXM = 80 + 1;
const int SIZE = 100 + 1; 

string add(string s1, string s2) {
    int a[SIZE] = { 0 }, b[SIZE] = { 0 }, c[SIZE] = { 0 };
    int size_a = s1.size(), size_b = s2.size();
    for (int i = 0; i < size_a; i++) a[size_a - i] = s1[i] - '0';
    for (int i = 0; i < size_b; i++) b[size_b - i] = s2[i] - '0';
    int size_c = 1, x = 0;
    while (size_c <= size_a || size_c <= size_b) {
        c[size_c] = a[size_c] + b[size_c] + x;
        x = c[size_c] / 10;
        c[size_c] %= 10;
        size_c++;
    }
    c[size_c] = x;
    while (size_c > 1 && c[size_c] == 0) size_c--;
    string res;
    res.resize(size_c);
    for (int i = size_c; i >= 1; i--) res[size_c - i] = c[i] + '0';
    return res;
}

string mul(string s1, string s2) {
    int a[SIZE] = { 0 }, b[SIZE] = { 0 }, c[SIZE] = { 0 };
    int size_a = s1.size(), size_b = s2.size();
    for (int i = 0; i < size_a; i++) a[size_a - i] = s1[i] - '0';
    for (int i = 0; i < size_b; i++) b[size_b - i] = s2[i] - '0';  
    for (int i = 1; i <= size_a; i++) {
        int x = 0;
        for (int j = 1; j <= size_b; j++) {
            int now = i + j - 1;
            c[now] += a[i] * b[j] + x;
            x = c[now] / 10;
            c[now] %= 10;
        }
        c[i + size_b] = x;
    }
    int size_c = size_a + size_b;
    while (size_c > 1 && c[size_c] == 0) size_c--;
    string res;
    res.resize(size_c);
    for (int i = size_c; i >= 1; i--) res[size_c - i] = c[i] + '0';
    return res;
}

int n, m;
string a[MAXM], pow2[MAXM], f[MAXN][MAXM], ans;

inline string max(string a, string b) {
    if (a.size() > b.size()) return a;
    if (a.size() < b.size()) return b;
    for (int i = 0; i < a.size(); i++) {
        if (a[i] > b[i]) return a;
        if (a[i] < b[i]) return b;
    }
    return a;
}

int main(int argc, char *argv[]) {
    cin >> n >> m;
    pow2[0] = "1";
    for (int i = 1; i <= m; i++) pow2[i] = mul(pow2[i - 1], "2");
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> a[j];
            f[j][j] = mul(pow2[m], a[j]);
        }
        for (int d = 1; d <= m - 1; d++) {
            for (int l = 1; l <= m - d; l++) {
                int r = l + d;       
                f[l][r] = max(add(f[l + 1][r], mul(pow2[m - d], a[l])), add(f[l][r - 1], mul(pow2[m - d], a[r])));
            }
        }
        ans = add(ans, f[1][m]);
    }
    cout << ans << endl;
    return 0;
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值