【倍增】T-shirt @2018acm徐州邀请赛 I

问题 I: T-shirt

时间限制: 1 Sec   内存限制: 64 MB

题目描述

JSZKC is going to spend his vacation! 
His vacation has N days. Each day, he can choose a T-shirt to wear. Obviously, he doesn’t want to wear a singer color T-shirt since others will consider he has worn one T-shirt all the time. 
To avoid this problem, he has M different T-shirt with different color. If he wears A color T-shirt this day and B color T-shirt the next day, then he will get the pleasure of f[A][B].(notice: He is able to wear one T-shirt in two continuous days but may get a low pleasure) 
Please calculate the max pleasure he can get. 

输入

The input file contains several test cases, each of them as described below. 
  • The first line of the input contains two integers N,M (2 ≤ N≤ 100000, 1 ≤ M≤ 100), giving the length of vacation and the T-shirts that JSZKC has.   
  • The next follows M lines with each line M integers. The jth integer in the ith line means f[i][j](1<=f[i][j]<=1000000). 
There are no more than 10 test cases. 

输出

One line per case, an integer indicates the answer 

样例输入

3 2
0 1
1 0
4 3
1 2 3
1 2 3
1 2 3

样例输出

2
9

 

meaning

给一个m×m的矩阵,data[i][j]表示第一天在i点第二天在j点的收益,问n天的最大收益。

solution

f[k][i][j] 表示第一天在i点,2^k天后在j点的最大收益。

f[0][i][j] = data[i][j];

f[k][i][j] = max(f[k][i][j],f[k-1][i][p]+f[k-1][p][j]);

d[i][j] 表示从i点到j点的最大收益。

code

#define IN_LB() freopen("C:\\Users\\acm2018\\Desktop\\in.txt","r",stdin)
#define OUT_LB() freopen("C:\\Users\\acm2018\\Desktop\\out.txt","w",stdout)
#define IN_PC() freopen("C:\\Users\\hz\\Desktop\\in.txt","r",stdin)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxm = 105;

ll f[20][maxm][maxm];
ll d[2][maxm][maxm];
int main() {
//    IN_LB();
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF) {
        memset(f,0,sizeof f);
        memset(d,0,sizeof d);
        for(int i=0; i<m; i++) {
            for(int j=0; j<m; j++) {
                scanf("%lld",&f[0][i][j]);
            }
        }
        for(int k=1; k<20; k++)
            for(int l=0; l<m; l++)
                for(int i=0; i<m; i++)
                    for(int j=0; j<m; j++)
                        f[k][i][j] = max(f[k][i][j],f[k-1][i][l]+f[k-1][l][j]);
        n--;
        int cnt = 0;
        for(int k=19; k>=0; k--) {
            if(n>(1<<k)) {
                n-=(1<<k);
                for(int l = 0; l<m; l++) {
                    for(int i=0; i<m; i++) {
                        for(int j=0; j<m; j++) {
                            d[cnt][i][j]=max(d[cnt][i][j],d[cnt^1][i][l]+f[k][l][j]);
                        }
                    }
                }
                cnt^=1;
            }
        }
        if(n==1) {
            for(int l = 0; l<m; l++) {
                for(int i=0; i<m; i++) {
                    for(int j=0; j<m; j++) {
                        d[cnt][i][j]=max(d[cnt][i][j],d[cnt^1][i][l]+f[0][l][j]);
                    }
                }
            }
        }
        ll ans = 0;
        for(int i=0; i<m; i++) {
            for(int j=0; j<m; j++) {
                ans = max(ans,d[cnt][i][j]);
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}



转载于:https://www.cnblogs.com/NeilThang/p/9356601.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值