*TEST 10 for NOIP 迷幻测试 (230/300)

头更更大

这个10月完就要去搞NOIP了。。。

10月30天也就3次测试。。。为保佑进省一我还是每次测试玩都写个总结。。


。。↑↑↑首先有几个人发现并不只有三次测试。。。

boomshakalaka。。。第一题写炸。。。
第二题打没讨论全的Dp得了80分诶嘿嘿A_A
第三题一开始数据太水打模拟都能AC。。。然后凯爷当然厚道地改了数据。

这里写图片描述

是!的!我!没!图!了!

下面面详细解答:

T1 刮刮卡(50/100)————————

神秘代码:1997

problem

题意
类似于hdu”重温世界杯“,给你一堆卡,每张卡有A,B两个值,每次加上B值减去A值,当值为负时退出。可以把开头的几张牌按顺序挪到最后面。(1,2,3)->(3,1,2)问怎么挪可以保证拿到的B值的和最大。
样例数据

  • 输入 
    5
    4 6 2 8 4
    1 5 7 9 2

  • 输出
    4

solution

100%的正解用到了单调队列(然而我是滚动数组)
然后 莫名其妙地 暴成了50分。。。
一开始一直怀疑是评测机的问题。。。后来有人给我看了这个地方:

int pos(int x)
{
    if(x<=n)return x;
    else    return x-n;
}

然后我倒回去去看了我的滚动数组。。。

    int cnt=0;
    for(int i=1;i<=3*n;i++)//<=注意:是3n
    {
        jud+=c[pos(i)].b-c[pos(i)].a;
        tot+=c[pos(i)].b;
        cnt++;
        if(jud<0||cnt==n) 
        {
            if(tot>ans){ans=tot;loc=dot;}
            jud=0;tot=0;dot=pos(i+1);cnt=0;
        }
    }

。。。才发现我爆炸的原因是。。。滚动数组没有用MOD。。。。。。
又一次以神奇的姿势(凯爷用语)神奇的GG了。orz

然而实际上还不用那么麻烦。因为花掉的钱的和等于用去的钱的和,所以总有一种方案我们可以拿到所有的积分。所以只需要找从哪里开始就行了。这里要用到前缀和。从终点,也就是从右往左扫前缀和找前缀和最大的那张牌就行。

章末附上正解代码。(滚动数组版)

T2 矩阵(80/100)————————

神秘代码:1998

problem

题意
 给一个N行M列的矩阵,挑出K个互不重叠的子矩阵,得分为这些子矩阵中的数值和,求这个数值的最大值。
 数据范围为:1<=N<=100,1<=M<=2,1<=K<=10,|数值|<=1000000;
样例数据

  • 输入
    3 2 2
    1 -3
    2 3
    -2 3

  • 输出
    9

solution

注意M的最大值仅为2。

40%的强行一位数组用 最大连续区间和 再用 s[i][j] 表示用了i个集合,尾数标号为j的最大区间和就行了。

80%的搞两个40%的算法(m=2嘛)再Dp判一下哪一列用几个区间。
数据略水,竟然给一个压根没讨论完情况的Dp这么多分??不过我收下了诶嘿嘿A_A

100%的有k x n^3的,有k x n^2的,还有k x n的。。。
感觉最后能打出k x n^3的就已经很不错了。。。
这里是这道题轮廓线Dp的代码。

T3 裁剪表格(80/100)————————

神秘代码:1999

problem

题意
给一个N*M的矩阵,每次交换两个形状完全相同的且互不重叠而且没有公共边界的子矩阵,输出最后结果。 (3秒)
样例数据

  • 输入 
    4 4 2
    1 1 2 2
    1 1 2 2
    3 3 4 4
    3 3 4 4
    1 1 3 3 2 2
    3 1 1 3 2 2

  • 输出
    4 4 3 3
    4 4 3 3
    2 2 1 1
    2 2 1 1

solution

事实上当时考试拿到卷子第一眼扫过去就认定了摔个模拟上去就走.
然后干完第二题后回来再看暴力。。。
嗯嗯嗯??有种可能AC的感觉怎么回事???
这里写图片描述
交完代码后:
这里写图片描述

AC了一道T3题,激动!

这里写图片描述

当然马上被凯爷改了数据就成这样了:(好像变化不大)

这里写图片描述

然后有一个大佬说在不开O2的情况下把所有for循环里的int改成register int会有神奇的效果。
改了之后:

这里写图片描述
这里写图片描述

还!有!什!么!能!阻!止!我!A ! C !

这里写图片描述

有!凯爷再改一次数据!

下面是 正!解!
正解更加玄学:链表结构!(凯爷链表大佬)

别告诉我你不知道什么是链表

从每一个点向它的下方和右方连接,然后转移时就直接往下数往右数再把边上的点的连接互换就行了。。。
好吧我这么说好像更不好解释了。。。。。。
看代码吧。。
友情链接

感想

现在才发现所谓的Dp转移方程不是推出来的而是背出来的。。
同一类的Dp题都有一定的套路。。。才知道啊智障
暴力大法好!
暴力大法好!!
暴力大法好!!!

代码

以后代码都放在章末。

T1

my/std.cpp

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;

inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

inline void write(int x)
{
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}

const int kkk=1000500;

int n,f[kkk];
int ans=0,tot=0,jud=0,dot=0,loc=0;
struct node{int a,b;}c[kkk];

int pos(int x)
{
    if(x<=n)return x;
    else    return x-n;
}

int main()
{

    n=read();
    for(int i=1;i<=n;i++)c[i].b=read();
    for(int i=1;i<=n;i++)c[i].a=read();

    jud=0,ans=0,tot=0,dot=1,loc=0;

    int cnt=0;
    for(int i=1;i<=2*n;i++)
    {
        jud+=c[pos(i)].b-c[pos(i)].a;
        tot+=c[pos(i)].b;
        cnt++;
        if(jud<0||cnt==n) 
        {
            if(tot>ans){ans=tot;loc=dot;}
            jud=0;tot=0;dot=pos(i+1);cnt=0;
        }
    }
    ans=max(ans,tot);

    cout << loc-1 << endl;

    return 0;
}

T2

my.cpp

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;

inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

inline void write(int x)
{
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}

int n,m,o,a[105][3],f[4][105][105],sum[4][105][105];
int ans=0,flag=1;

int main()
{

    n=read();   m=read();   o=read();
    for(int i=1;i<=n;i++)
      for(int j=1;j<=m;j++)
      {
        a[i][j]=read(),ans+=a[i][j];
          if(a[i][j]<0)flag=0;
      }

    if(flag){cout<<ans<<endl;return 0;}
    memset(f,0,sizeof(f));  
    memset(sum,-63,sizeof(sum));    

    for(int i=1;i<=n;i++)
    for(int j=i;j<=n;j++)
    f[1][i][j]=max(f[1][i][j-1],0)+a[j][1]; 

    for(int i=1;i<=o;i++)
    for(int j=i;j<=n;j++)
    for(int k=i-1;k<=j-1;k++)
    {
        sum[1][i][j] = max(sum[1][i][j],max(sum[1][i-1][k],0)+f[1][k+1][j]);
        ans = max(ans,sum[1][i][j]);
        sum[0][i][j] = max(ans,sum[0][i][j]);       
    }

    if(m>1)
    {           
        for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j++)
        f[2][i][j]=max(f[2][i][j-1],0)+a[j][2]; 

        for(int i=1;i<=o;i++)
        for(int j=i;j<=n;j++)
        for(int k=i-1;k<=j-1;k++)
        {
            sum[2][i][j] = max(sum[2][i][j],max(sum[2][i-1][k],0)+f[2][k+1][j]);
            ans = max(ans,sum[2][i][j]);
            sum[0][i][j] = max(ans,sum[0][i][j]);           
        }           

        for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j++)
        f[3][i][j]=max(f[3][i][j-1],0)+a[j][1]+a[j][2]; 

        for(int i=1;i<=o;i++)
        for(int j=i;j<=n;j++)
        for(int k=i-1;k<=j-1;k++)
        {
            sum[3][i][j] = max(sum[3][i][j],max(sum[3][i-1][k],0)+f[3][k+1][j]);
            ans = max(ans,sum[3][i][j]);
            sum[0][i][j] = max(ans,sum[0][i][j]);           
        }       

        for(int i=1;i<=o;i++)
        for(int j=i;j<=n;j++)       
        for(int j1=i;j1<=j;j1++)            
        for(int j2=i;j2<=j;j2++)
        for(int g=0;g<=i;g++)
        {
            sum[0][i][j] = max(sum[0][i][j],((g)?(sum[1][g][j1]):(0))+((i-g)?(sum[2][i-g][j2]):(0)));
            ans = max(ans,sum[0][i][j]);
        }       

//      for(int i=1;i<=o;i++)
//      for(int j=i;j<=n;j++)
//      for(int k=i-1;k<=j-1;k++)
//      {
//          if(sum[1][i][j]+sum[2][i][j]==sum[3][i][j])
//          sum[0][i][j]=max()
//      }
    }

    cout << ans << endl;
    return 0;
}

std.cpp

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;

inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

inline void write(int x)
{
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}

int n,m,o,a[105][3];
int ans=0,flag=1;

int main()
{
    n=read();   m=read();   o=read();
    for(int i=1;i<=n;i++)
      for(int j=1;j<=m;j++)
      {
        a[i][j]=read(),ans+=a[i][j];
          if(a[i][j]<0)flag=0;
      }

    if(flag){cout<<ans<<endl;return 0;}
    ans=-99999999;

    if(m==1)
    {
        int f[105][105],sum[105][105];
        memset(f,0,sizeof(f));  
        memset(sum,-63,sizeof(sum));    

        for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j++)
        f[i][j]=max(f[i][j-1],0)+a[j][1];   

        for(int i=1;i<=o;i++)
        for(int j=i;j<=n;j++)
        for(int k=i-1;k<=j-1;k++)
        {
            sum[i][j] = max(sum[i][j],max(sum[i-1][k],0)+f[k+1][j]);
            ans = max(ans,sum[i][j]);   
        }
    }

    else if(m>1)
    {           
        int f[105][105][20],sum[105][3];
        memset(f,-10,sizeof(f));  

        for(int i=0;i<=n;i++)
          for(int j=0;j<=n;j++)
           f[i][j][0]=0;

        for(int i=1;i<=n;i++)
          for(int j=1;j<=m;j++)
            sum[i][j] += sum[i-1][j]+a[i][j];

        for(int i=1;i<=n;i++)
          for(int j=1;j<=n;j++)
            for(int k=1;k<=o;k++)
            {
                f[i][j][k]=max(f[i-1][j][k],f[i][j-1][k]);

                for(int g=0;g<=i-1;g++)
                    f[i][j][k]=max(f[i][j][k],f[g][j][k-1]+sum[i][1]-sum[g][1]);

                for(int g=0;g<=j-1;g++)
                    f[i][j][k]=max(f[i][j][k],f[i][g][k-1]+sum[j][2]-sum[g][2]);

                if(i==j)
                for(int g=0;g<=j-1;g++) 
                    f[i][j][k]=max(f[i][j][k],f[g][g][k-1]+sum[i][1]-sum[g][1]+sum[j][2]-sum[g][2]);    
            }
        ans = max(ans,f[n][n][o]);
    }

    cout << ans << endl;
    return 0;
}

T3

my.cpp

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;

inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

inline void write(int x)
{
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}

int n,m,q;
int pre,flag=1;
int r1,c1,r2,c2,h,w; 
int mar[1005][1005];

int main()
{
    n=read();   m=read();   q=read();
    for(register int i=1;i<=n;i++)  
      for(register int j=1;j<=m;j++)
      {
        mar[i][j]=read();

        if(!pre)pre=mar[i][j];
        else if(mar[i][j]!=pre)flag=0;
      }
    while(q--)
    {
        r1=read();c1=read();r2=read();c2=read();h=read();w=read();
        if(!flag)
        {
            for(register int i=1;i<=h;i++)
              for(register int j=1;j<=w;j++)
              {
                int k = mar[r1+i-1][c1+j-1];
                mar[r1+i-1][c1+j-1] = mar[r2+i-1][c2+j-1];
                mar[r2+i-1][c2+j-1] = k;
              }
        }
    }
    for(register int i=1;i<=n;i++)
    {   
      for(register int j=1;j<=m;j++)
        cout<<mar[i][j]<<" ";
      cout<<endl;
    }
    return 0;
}

std.cpp

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#define ll long long
using namespace std;

int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
    if(c=='-')f=-1,c=getchar();
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}

const int N=1005;
int n,m,Q,num;
int f[N*N][2],lab[N][N],v[N*N];

int getlab(int a,int b)
{
    int p=lab[0][0];
    for(int i=1;i<=a;i++)p=f[p][1];
    for(int i=1;i<=b;i++)p=f[p][0];
    return p;
}

int main()
{
    //freopen("table.in","r",stdin);
    //freopen("table.out","w",stdout);
    int a,b,c,d,h,w;
    n=getint(),m=getint(),Q=getint();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            v[lab[i][j]=++num]=getint();
    for(int i=0;i<=m+1;i++)
        lab[0][i]=++num,lab[n+1][i]=++num;
    for(int i=1;i<=n;i++)
        lab[i][0]=++num,lab[i][m+1]=++num;
    for(int i=0;i<=n;i++)
        for(int j=0;j<=m;j++)
        {
            f[lab[i][j]][0]=lab[i][j+1];
            f[lab[i][j]][1]=lab[i+1][j];
        }
    while(Q--)
    {
        a=getint(),b=getint(),c=getint(),d=getint(),h=getint(),w=getint();
        int p1=getlab(a-1,b-1),p2=getlab(c-1,d-1);
        int t1,t2,ww,hh;
        for(t1=p1,t2=p2,ww=1;ww<=w;ww++)swap(f[t1=f[t1][0]][1],f[t2=f[t2][0]][1]);
        for(hh=1;hh<=h;hh++)swap(f[t1=f[t1][1]][0],f[t2=f[t2][1]][0]);
        for(t1=p1,t2=p2,hh=1;hh<=h;hh++)swap(f[t1=f[t1][1]][0],f[t2=f[t2][1]][0]);
        for(ww=1;ww<=w;ww++)swap(f[t1=f[t1][0]][1],f[t2=f[t2][0]][1]);
    }
    for(int i=1,p=lab[0][0];i<=n;i++)
    {
        for(int j=1,t=p=f[p][1];j<=m;j++)
            cout<<v[t=f[t][0]]<<" ";
        cout<<endl;
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值