您的位置:首页 > 其它

P1005 矩阵取数游戏

2017-08-24 02:09 211 查看

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 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: