P1005 矩阵取数游戏

Posted 范仁义

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1005 矩阵取数游戏相关的知识,希望对你有一定的参考价值。

P1005 矩阵取数游戏

题目描述

帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数。游戏规则如下:

1.每次取数时须从每行各取走一个元素,共n个。m次后取完矩阵所有元素;

2.每次取走的各个元素只能是该元素所在行的行首或行尾;

3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值*2^i,其中i表示第i次取数(从1开始编号);

4.游戏结束总得分为m次取数得分之和。

帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。

输入输出格式

输入格式:

 

输入文件game.in包括n+1行:

第1行为两个用空格隔开的整数n和m。

第2~n+1行为n*m矩阵,其中每行有m个用单个空格隔开的非负整数。

数据范围:

60%的数据满足:1<=n, m<=30,答案不超过10^16

100%的数据满足:1<=n, m<=80,0<=aij<=1000

 

输出格式:

 

输出文件game.out仅包含1行,为一个整数,即输入矩阵取数后的最大得分。

 

输入输出样例

输入样例#1:
2 3
1 2 3
3 4 2
输出样例#1:
82

说明

NOIP 2007 提高第三题

 

思路:

1、贪心不行

贪心思路:

每次选取 两边都较小的值 让较小的值乘以低次幂 而较高的值留在后面 总之都要取完 而贪心只有20分 

贪心错误实例:

如果有一组数据是4,3,10,1,1,1,1,1,1,1,1,5,5,5,5,9贪心就是错的,会先把5取完,然而应该先取1。

贪心错误原因:

前面的状态对后面有影响,这已经失去了贪心的条件。

 

 

2、动态规划

对于每一行,其实都是独立的,也就是每一行的最优值之和即为答案。而且看题目数据规模,要加高精度。

状态:

f[i][j]表示取下标为 i至j 的数字所能得到的最大得分

状态转移方程:

f[i][j]=2*max(f[i][j-1]+a[j],f[i+1][j]+a[i])

一个表示取头,一个表示取尾

这里相当于每到下一层都把上一层乘了2,越在内层,乘2的次数越多

 

60分代码

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 int n,m,a[81];
 6 long long s,f[81][81];//f[j][k]j到k最大值 
 7 int main()
 8 {
 9     scanf("%d%d",&n,&m);
10     for(int i=1;i<=n;i++)//i行数 
11     {
12         for(int j=1;j<=m;j++)
13         {
14             scanf("%d",&a[j]);
15             f[j][j]=2*a[j];
16         }
17         for(int j=2;j<=m;j++)//区间长度 
18             for(int k=1;k+j-1<=m;k++)//起点 
19             {
20                 int g=k+j-1;//终点 
21                 long long tmp=2*max(f[k+1][g]+a[k],f[k][g-1]+a[g]);
22                 f[k][g]=max(f[k][g],tmp);
23             }
24         s+=f[1][m];
25         memset(f,0,sizeof(f));
26     }
27     printf("%lld\n",s);
28     return 0;
29 }

 

100分代码

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 using namespace std;
  5 int n,m,a[81][101],s[101],tmp[4][101],f[81][81][101];//f[j][k]j到k最大值 
  6 void init(int i,int aa[])//将i赋值给aa[] 
  7 {
  8     if(i==0)
  9         aa[0]=1;
 10     while(i!=0)
 11     {
 12         aa[0]++;
 13         aa[aa[0]]=i%10;
 14         i/=10;
 15     }
 16 }
 17 void jin(int aa[])//进位操作 
 18 {
 19     for(int i=1;i<=aa[0];i++)
 20     {
 21         aa[i+1]+=aa[i]/10;
 22         aa[i]%=10;
 23     }
 24     if(aa[aa[0]+1]!=0)
 25         aa[0]++;
 26     while(aa[aa[0]]/10!=0)
 27     {
 28         aa[aa[0]+1]+=aa[aa[0]]/10;
 29         aa[aa[0]]%=10;
 30         aa[0]++;
 31     }
 32     if(aa[aa[0]]==0&&aa[0]!=1)
 33         aa[0]--;
 34 }
 35 void jia1(int aa[],int bb[],int cc[])//将aa[]与bb[]相加,存入cc[] 
 36 {
 37     for(int i=1;i<=aa[0]||i<=bb[0];i++)
 38         cc[i]=aa[i]+bb[i];
 39     cc[0]=max(bb[0],aa[0]);
 40     jin(cc);
 41 }
 42 void jia2(int aa[],int bb[])//将aa[]加bb[],存入bb[] 
 43 {
 44     for(int i=1;i<=aa[0];i++)
 45         bb[i]+=aa[i];
 46     bb[0]=max(bb[0],aa[0]);
 47     jin(bb);
 48 }
 49 bool maxx(int aa[],int bb[])//返回aa[],bb[]中最大值 
 50 {
 51     if(aa[0]>bb[0])
 52         return 1;
 53     else if(aa[0]<bb[0])
 54         return 0;
 55     else
 56         for(int i=aa[0];i>=1;i--)
 57         {
 58             if(aa[i]>bb[i])
 59                 return 1;
 60             else if(aa[i]<bb[i])
 61                 return 0;
 62         }
 63     return 0;
 64 }
 65 void fang(int aa[],int bb[])//将aa[]赋值给bb[] 
 66 {
 67     for(int i=1;i<=aa[0];i++)
 68         bb[i]=aa[i];
 69     bb[0]=aa[0];
 70 }
 71 void dbbl(int aa[])//将aa[]翻倍 
 72 {
 73     for(int i=1;i<=aa[0];i++)
 74         aa[i]*=2;
 75     jin(aa);
 76 }
 77 int main()
 78 {
 79     scanf("%d%d",&n,&m);
 80     for(int i=1;i<=n;i++)
 81     {
 82         int x;
 83         for(int j=1;j<=m;j++)
 84         {
 85             scanf("%d",&x);
 86             init(x,a[j]);
 87             init(2*x,f[j][j]);
 88         }
 89         for(int j=2;j<=m;j++)//区间长度 
 90             for(int k=1;k+j-1<=m;k++)//起点 
 91             {
 92                 int g=k+j-1;//终点 
 93                 jia1(f[k+1][g],a[k],tmp[1]);
 94                 jia1(f[k][g-1],a[g],tmp[2]);
 95                 if(maxx(tmp[1],tmp[2]))
 96                     fang(tmp[1],tmp[3]);
 97                 else
 98                     fang(tmp[2],tmp[3]);
 99                 dbbl(tmp[3]);
100                 if(maxx(tmp[3],f[k][g]))
101                     fang(tmp[3],f[k][g]);
102                 memset(tmp,0,sizeof(tmp));
103             }
104         jia2(f[1][m],s);
105         memset(f,0,sizeof(f));
106         memset(a,0,sizeof(a));
107     }
108     for(int i=s[0];i>=1;i--)
109         printf("%d",s[i]);
110     printf("\n");
111     return 0;
112 }

 

以上是关于P1005 矩阵取数游戏的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P1005 矩阵取数游戏

洛谷 P1005 矩阵取数游戏

P1005矩阵取数游戏

P1005 矩阵取数游戏

P1005 矩阵取数游戏

洛谷 P1005 矩阵取数游戏