zoukankan      html  css  js  c++  java
  • 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
    ",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("
    ");
    111     return 0;
    112 }
  • 相关阅读:
    hdu 5100 n*n棋盘放k*1长方条最多覆盖面积
    poj 3635/hdu 1676 Full Tank? 车辆加油+最短路
    poj 3613 经过k条边最短路 floyd+矩阵快速幂
    2014上海全国邀请赛 解题报告
    漫谈程序员系列:看看你离优秀有多远
    C2第七次作业解题报告
    C++ STL
    hdu 5098 双队列拓扑排序
    深度学习数据集 近百个开源数据集
    helper工具包——基于cifar10数据集的cnn分类模型的模块
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/7421098.html
Copyright © 2011-2022 走看看