题目描述
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.
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).
输出
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
题意:求f[a][b]+f[b][c]+f[c][d]+...+f[p][q](有n-1项)的最大值;
思路:从简单情况入手,当n=2时,求f[a][b]的最大值,两重循环遍历即可;
当n=3时,求f[a][b]+f[b][c]的最大值,三重循环遍历即可;
当n=4时,自然可以四重循环遍历,,,我们换一个角度考虑,可以将f[a][c]的值以f[a][b]+f[b][c]中的最大值替代(得到新的最优的f[1~m][1~m]——此时f[i][j]表示第一天穿i,第三天穿j可以得到的最大快乐),接着求f[a][c]+f[c][d]的最大值,回到n=3的情况,也就是进行三重循环遍历;
当n=5时类似,将f[a][d]以f[a][c]+f[c][d]中的最值替代后,计算f[a][d]+f[d][e]的最值,与此同时,得到新的f[1~m][1~m];
总结一下,相当于不断地更新f[1~m][1~m];一开始f[i][j]表示第1天穿i,第2天穿j的所能得到的最大快乐,更新k次后f[i][j]表示第1天穿i,第2+k天穿j所能得到的最大快乐;
这样的话需要在原始f上更新n-2次得到最终f——f[i][j]表示第一天穿i,第n天穿j所能得到的最大快乐;每一次更新的复杂度为O(m^2),暴力n次更新复杂度O(n*m^2)会超时;
可以将更新视为定义在f上的一种运算'#',f经n-2次更新,可视为f#f#...#f(n-1个f相#),用“快速#”计算n-1个f相#即可;类似于矩阵快速幂;
AC代码:
#include <iostream> #include<cstdio> #include<cstring> typedef long long ll; using namespace std; ll n,m; struct Matrix{ ll f[110][110]; Matrix(){memset(f,0,sizeof(f));} Matrix operator *(Matrix & mat){ Matrix ret; for(ll i=1;i<=m;i++){ for(ll k=1;k<=m;k++){ for(ll j=1;j<=m;j++){ ret.f[i][j]=max(ret.f[i][j],mat.f[i][k]+f[k][j]); } } } return ret; } }; Matrix qpow(Matrix a,ll b){ Matrix ret; while(b){ if(b&1) ret=ret*a; a=a*a; b>>=1; } return ret; } int main() { while(scanf("%lld%lld",&n,&m)!=EOF){ Matrix mat; for(ll i=1;i<=m;i++){ for(ll j=1;j<=m;j++){ scanf("%lld",&mat.f[i][j]); } } mat=qpow(mat,n-1); ll ans=0; for(ll i=1;i<=m;i++){ for(ll j=1;j<=m;j++){ ans=max(ans,mat.f[i][j]); } } printf("%lld ",ans); } return 0; }