http://hihocoder.com/contest/offers13/problems

题目1 : 风格不统一如何写程序

首先:输入保证组成变量名的单词只包含小写字母。

做法:只要对不同的部分进行修改即可

注意:只有一个单词,两个方法的单词都一样

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h> int main()
{
long n,i,k,len;
char s[];
bool vis;
scanf("%ld",&n);
for (k=;k<=n;k++)
{
scanf("%s",s);
len=strlen(s);
vis=false;
for (i=;i<len;i++)
if (s[i]=='_')
{
vis=true;
break;
}
if (vis)
{
for (i=;i<len;i++)
if (s[i]=='_')
{
printf("%c",s[i+]-);
i++;
}
else
printf("%c",s[i]);
}
else
{
for (i=;i<len;i++)
if (s[i]<)
{
printf("_");
printf("%c",s[i]+);
}
else
printf("%c",s[i]);
}
printf("\n");
} return ;
}

最大子矩阵

注意:满足条件最大的子矩阵所包含的元素数目。如果没有子矩阵满足条件,输出-1。

与求最大子矩阵题目(hdu1559子矩阵的元素之和最大)方法类似。

设row[x][y]:第x行中前y个数的和

则row[x][q]-row[x][p]:第x行中第p+1~第q个数的和

行x~y列u~v的矩形的元素之和:row[x][v]-row[x][u-1]+row[x+1][v]-row[x+1][u-1]+…+row[y][v]-row[y][u-1]

按照列固定:u~v (第u个数到第v个数), 进行行的探索。

假设从行第p个数开始向下边2递增(每次p加1),假设到第q个数数值和第一次超过设定值,计算矩形面积(q-p)*(v-u+1),

然后从第p个数开始向下边1递增(每次p+1),直到数值和第一次小于设定值。

然后继续操作,直到v=n+1,结束。

而对于每个列固定:x~y,共m*m次。而对于每次行的探索,每个数最多加入一次,每个数最多减去一次,共2*n次。

时间复杂度O(m*m*n)。当然如果m>n,可以把行固定,进行列的探索,时间复杂度O(m*n*n)。

即时间复杂度O(m*n*min(m,n))。

参见程序,比较巧妙。

 #include <stdio.h>
#include <stdlib.h> long max(long a,long b)
{
if (a>b)
return a;
else
return b;
} int main()
{
long n,m,f[][],row[][];
long i,j,s,t,maxg=,maxvalue,ans=,bian,x,y;
scanf("%ld%ld%ld",&n,&m,&maxvalue);
for (i=;i<=n;i++)
{
//single row
row[i][]=;
for (j=;j<=m;j++)
{
scanf("%ld",&f[i][j]);
row[i][j]=row[i][j-]+f[i][j];
}
}
//s+1~t
for (s=;s<m;s++)
for (t=s+;t<=m;t++)
{
bian=t-s;
ans=;
x=;
y=;
i=;
while (i!=n+)
{
for (i=y;i<=n;i++)
{
ans=ans+row[i][t]-row[i][s];
if (ans>maxvalue)
break;
}
//x~i-1
maxg=max(maxg,(i-x)*bian);
//使x~i <=maxvalue
//最终的可能性是减为0
while (ans>=maxvalue)
{
ans=ans-row[x][t]+row[x][s];
x++;
}
//使下一次从i+1的位置开始加
y=i+; }
}
if (maxg==)
printf("-1\n");
else
printf("%ld\n",maxg);
return ;
}
/*
5 5 3
1 2 3 2 1
2 3 1 2 3
1 2 1 3 1
1 2 1 3 1
1 2 3 3 3
*/
/*
20 20 31
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
*/

题目3 : 一人麻将

注意:无法胡牌输出-1。

方法:可以cheat!!!经测试,输出-1,可得10分。那时我去参加zoj的网赛,没有时间了,就果断cheat!(noip及其有效,对一些特殊且容易写的部分)

参见程序,程序长,但时间消耗比较短

 #include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> struct rec
{
long posu,posv;
}; struct node
{
long posu,posv,posw;
}; bool vis[];
struct node s[];
long ts,ee,minpos=; int cmp(const void *a,const void *b)
{
//posu<posv。对a,b中最大的牌(posv)进行升序排序(先拿到,先胡牌)
//a,b中最大的牌(posv)都不相同
return (*(struct rec *)a).posv - (*(struct rec *)b).posv;
} int cmp1(const void *a,const void *b)
{
return (*(struct node *)a).posw - (*(struct node *)b).posw;
} long max(long a,long b)
{
if (a>b)
return a;
else
return b;
} long min(long a,long b)
{
if (a>b)
return b;
else
return a;
} void dfs(long b,long step)
{
long i;
for (i=b;i<ts-step && s[i].posw<minpos;i++)
if (vis[s[i].posu] && vis[s[i].posv] && vis[s[i].posw])
{
if (step==)
{
//minpos=min(minpos,s[i].posw);
minpos=max(ee,s[i].posw);
break;
}
//else if (s[i].posw<minpos)
else
{
vis[s[i].posu]=false;
vis[s[i].posv]=false;
vis[s[i].posw]=false;
dfs(i+,step-);
vis[s[i].posu]=true;
vis[s[i].posv]=true;
vis[s[i].posw]=true;
}
}
} int main()
{
char str[];
//一张牌最多4个:2对,9*2=18种牌
//3:
//数字相连:(1,2,3)~(7,8,9) 每张牌有4种选择 4*4*4*8=502
//同数字:若有四张牌 1,2,3;2,3,4(若1,2,3与其它冲突,用2,3,4) 2*9=18
struct rec er[][],e[];
struct node san[][];
long ge[],gs[],te;
//pai[i][j]:i:对应a,b,c j:对应1~9,最多有4张牌
long n,x,y,t,pai[][][],ans[][];
long i,j,k,l,m;
for (i=;i<;i++)
for (j=;j<;j++)
ans[i][j]=;
scanf("%ld",&n); for (i=;i<;i++)
{
scanf("%s",str);
x=str[]-;
//-'1'
y=str[]-;
pai[x][y][ans[x][y]]=i;
ans[x][y]++;
}
for (i=;i<+n;i++)
{
scanf("%s",str);
x=str[]-;
y=str[]-;
pai[x][y][ans[x][y]]=i;
ans[x][y]++;
} //对子
for (i=;i<;i++)
{
ge[i]=;
for (j=;j<;j++)
{
//找最前面的配对
if (ans[i][j]>=)
{
er[i][ge[i]].posu=pai[i][j][];
er[i][ge[i]].posv=pai[i][j][];
ge[i]++;
}
//两个对子
if (ans[i][j]==)
{
er[i][ge[i]].posu=pai[i][j][];
er[i][ge[i]].posv=pai[i][j][];
ge[i]++;
}
}
qsort(er[i],ge[i],sizeof(struct rec),cmp);
} //至少拥有7个对子胡牌
//手中14张牌最多只能属于两个花色
//each 对子 没有相互影响
for (i=;i<;i++)
for (j=i+;j<;j++)
if (ge[i]+ge[j]>=)
{
x=;
y=;
t=;
while (x<ge[i] && y<ge[j] && t<)
{
t++;
if (er[i][x].posv<er[j][y].posv)
x++;
else
y++;
}
if (t==)
{
//use j
if (x==ge[i])
minpos=min(minpos,er[j][y].posv);
//use i
else if (y==ge[j])
minpos=min(minpos,er[i][x].posv);
else
minpos=min(minpos,min(er[i][x].posv,er[j][y].posv));
}
//use j
else if (x==ge[i])
minpos=min(minpos,er[j][y+-t].posv);
//use i
else
minpos=min(minpos,er[i][x+-t].posv);
} //三张牌
for (i=;i<;i++)
{
gs[i]=;
//同数字
for (j=;j<;j++)
{
if (ans[i][j]>=)
{
san[i][gs[i]].posu=pai[i][j][];
san[i][gs[i]].posv=pai[i][j][];
san[i][gs[i]].posw=pai[i][j][];
gs[i]++;
}
if (ans[i][j]==)
{
//相同的牌先给别人用了
san[i][gs[i]].posu=pai[i][j][];
san[i][gs[i]].posv=pai[i][j][];
san[i][gs[i]].posw=pai[i][j][];
gs[i]++;
}
}
//数字相连
for (j=;j<;j++)
for (k=;k<ans[i][j];k++)
for (l=;l<ans[i][j+];l++)
for (m=;m<ans[i][j+];m++)
{
san[i][gs[i]].posu=pai[i][j][k];
san[i][gs[i]].posv=pai[i][j+][l];
san[i][gs[i]].posw=pai[i][j+][m];
//posw存放最大值
if (san[i][gs[i]].posu>san[i][gs[i]].posw)
{
if (san[i][gs[i]].posu>san[i][gs[i]].posv)
{
t=san[i][gs[i]].posu;
san[i][gs[i]].posu=san[i][gs[i]].posw;
san[i][gs[i]].posw=t;
}
else
{
t=san[i][gs[i]].posv;
san[i][gs[i]].posv=san[i][gs[i]].posw;
san[i][gs[i]].posw=t;
}
}
else if (san[i][gs[i]].posv>san[i][gs[i]].posw)
{
t=san[i][gs[i]].posv;
san[i][gs[i]].posv=san[i][gs[i]].posw;
san[i][gs[i]].posw=t;
}
gs[i]++;
}
qsort(san[i],gs[i],sizeof(struct node),cmp1);
} //4*3+2
for (i=;i<;i++)
for (j=i+;j<;j++)
{
for (k=;k<;k++)
vis[k]=true; te=;
for (k=;k<ge[i];k++)
if (er[i][k].posv<minpos)
{
e[te]=er[i][k];
te++;
}
else
break;
for (k=;k<ge[j];k++)
if (er[j][k].posv<minpos)
{
e[te]=er[j][k];
te++;
}
else
break; ts=;
for (k=;k<gs[i];k++)
if (san[i][k].posw<minpos)
{
s[ts]=san[i][k];
ts++;
}
else
break;
for (k=;k<gs[j];k++)
if (san[j][k].posw<minpos)
{
s[ts]=san[j][k];
ts++;
} qsort(e,te,sizeof(struct rec),cmp);
qsort(s,ts,sizeof(struct node),cmp1); for (k=;k<te;k++)
{
if (e[k].posv<minpos)
{
ee=e[k].posv;
vis[e[k].posu]=false;
vis[e[k].posv]=false;
dfs(,);
vis[e[k].posu]=true;
vis[e[k].posv]=true;
}
else
break;
}
}
//No Solution: output -1
if (minpos==)
printf("-1\n");
else
printf("%ld\n",minpos-);
return ;
}

题目拓展:

有n个人,参加一个活动

每一个人有一个不和谐值

每三个人一个队伍

有若干组队伍

每一个队伍的不和谐值为三人的不和谐值的最大值
而不和谐值越小,完成一个活动越快

要求从n个人从选出m个队伍,
其中不同队伍里不能有相同的人

使不和谐值最大的队伍的不和谐值最小,
从而使得所有队伍完成时间最短

当三个人
变为两个人
变为k个人

结果如何???

题目4 : 骑士游历

一个通俗的想法:f[k][i][j],第k步可以到达(i,j)的步法总数。
f[k+1][i][j]是在第k步的基础上走1步到达(i,j)的步法总数。

 #include <stdio.h>
#include <stdlib.h>
#define yu 1000000007 int main()
{
long dx[]={-,-,-,-,,,,};
long dy[]={-,,-,,-,,-,};
long long f[][][];
long n,r,c,i,j,k,step,pre,cur,x,y;
long long ans;
scanf("%ld%ld%ld",&n,&r,&c);
for (i=;i<=;i++)
for (j=;j<=;j++)
f[][i][j]=;
f[][r][c]=;
pre=;
cur=;
for (step=;step<=n;step++)
{
for (i=;i<=;i++)
for (j=;j<=;j++)
f[cur][i][j]=;
for (i=;i<=;i++)
for (j=;j<=;j++)
for (k=;k<;k++)
{
x=i+dx[k];
y=j+dy[k];
if (x>= && x<= && y>= && y<=)
f[cur][x][y]=(f[cur][x][y]+f[pre][i][j])%yu;
} pre=pre ^ ;
cur=cur ^ ;
}
ans=;
for (i=;i<=;i++)
for (j=;j<=;j++)
ans=(ans+f[pre][i][j])%yu;
printf("%lld\n",ans);
return ;
}

满分做法:

二分思想,类似快速幂思想

f[k][x][y][u][v]:从(x,y)开始走k步到(u,v)总的走法

1.第k步到达第k+1步

f[k+1][x][y][u][v]=sum(f[k][x][y][p][q]+f[1][p][q][u][v])

2.第k步到达第2*k步

f[2*k][x][y][u][v]=sum(f[k][x][y][p][q],f[k][p][q][u][v])

快速幂:1->k,如10101=(((*2+)*2+)*2+)*2+1。(乘4次,加5次)

初始化f[1],只要创建四维数组即可。

时间复杂度:

1.第k步到达第2*k步:x,y,p,q,u,v可以取1~8:8*8*8*8*8*8=262144

最多执行log2(1000000000)<=30(向下取整)

262144*30=7864320

2.第k步到达第k+1步:f[k+1][x][y][u][v]=sum(f[k][x][y][p][q]+f[1][p][q][u][v]):计算每个x,y:8*8*8(走马,8种操作)=512

最多执行log2(1000000000)<=30(向下取整)

时间复杂度可以忽略不计

总的时间复杂度小于1000万,不会超时。

参见程序

 #include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define yu 1000000007 int main()
{
long dx[]={-,-,-,-,,,,};
long dy[]={-,,-,,-,,-,};
long long f[][][][],t[][][][],ans;
long n,r,c,m,ch[];
long x,y,p,q,u,v,k,i; scanf("%ld%ld%ld",&n,&r,&c);
for (x=;x<=;x++)
for (y=;y<=;y++)
for (u=;u<=;u++)
for (v=;v<=;v++)
f[x][y][u][v]=;
for (u=;u<=;u++)
for (v=;v<=;v++)
for (k=;k<;k++)
{
p=u-dx[k];
q=v-dy[k];
if (p>= && p<= && q>= && q<=)
f[p][q][u][v]=;
} m=(long)(log(n)/log(2.0));
ch[]=;
for (i=;i<=m;i++)
ch[i]=ch[i-]<<;
n-=ch[m];
for (i=m-;i>=;i--)
{
//*2
for (x=;x<=;x++)
for (y=;y<=;y++)
for (u=;u<=;u++)
for (v=;v<=;v++)
{
t[x][y][u][v]=f[x][y][u][v];
f[x][y][u][v]=;
} for (x=;x<=;x++)
for (y=;y<=;y++)
for (u=;u<=;u++)
for (v=;v<=;v++)
{
f[x][y][u][v]=;
for (p=;p<=;p++)
for (q=;q<=;q++)
f[x][y][u][v]=(f[x][y][u][v]+t[x][y][p][q]*t[p][q][u][v])%yu;
}
//+1
if (n>=ch[i])
{
for (x=;x<=;x++)
for (y=;y<=;y++)
for (u=;u<=;u++)
for (v=;v<=;v++)
{
t[x][y][u][v]=f[x][y][u][v];
f[x][y][u][v]=;
} for (u=;u<=;u++)
for (v=;v<=;v++)
for (k=;k<;k++)
{
p=u-dx[k];
q=v-dy[k];
if (p>= && p<= && q>= && q<=)
{
for (x=;x<=;x++)
for (y=;y<=;y++)
f[x][y][u][v]=(f[x][y][u][v]+t[x][y][p][q])%yu;
}
}
n-=ch[i];
}
}
ans=;
for (u=;u<=;u++)
for (v=;v<=;v++)
ans=(ans+f[r][c][u][v])%yu;
printf("%lld",ans);
return ;
}

[Offer收割]编程练习赛13 解题报告的更多相关文章

  1. Hihocoder [Offer收割]编程练习赛70 解题报告 By cellur925

    并没有第四题.(还不会矩阵乘法加速线性数列) 题目1 : 数位翻转 时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数 n,你可以进行若干次操作,每次操作可以翻转 ...

  2. [Offer收割]编程练习赛13 B.最大子矩阵[枚举]

    #1502 : 最大子矩阵 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个NxM的矩阵A和一个整数K,小Hi希望你能求出其中最大(元素数目最多)的子矩阵,并且该 ...

  3. hihocoder offer收割编程练习赛13 D 骑士游历

    思路: 矩阵快速幂. 实现: #include <iostream> #include <cstdio> #include <vector> using names ...

  4. 【[Offer收割]编程练习赛13 C】 一人麻将

    [题目链接]:http://hihocoder.com/problemset/problem/1503 [题意] [题解] 一直在纠结如果没胡的话要扔掉哪一个麻将; 但其实可不用扔的,全部存起来就好了 ...

  5. 【[Offer收割]编程练习赛13 D】骑士游历(矩阵模板,乘法,加法,乘方)

    [题目链接]:http://hihocoder.com/problemset/problem/1504 [题意] [题解] 可以把二维的坐标转成成一维的; 即(x,y)->(x-1)*8+y 然 ...

  6. 【[Offer收割]编程练习赛13 B】最大子矩阵(别人的思路)

    [题目链接]:http://hihocoder.com/problemset/problem/1502 [题意] [题解] 枚举矩形的最上面的行数和最下面的行数(i,j且i<=j); 然后一个变 ...

  7. 【[Offer收割]编程练习赛13 B】最大子矩阵(自己的思路)

    [题目链接]:http://hihocoder.com/contest/offers13/problem/2 [题意] [题解] 算出1..250*250这些数字每个数字的所有因子(成对的那种,即x* ...

  8. 【[Offer收割]编程练习赛13 A】风格不统一如何写程序

    [题目链接]:http://hihocoder.com/problemset/problem/1501 [题意] [题解] 模拟题 [Number Of WA] 1 [完整代码] #include & ...

  9. hihocoder [Offer收割]编程练习赛4

    描述 最近天气炎热,小Ho天天宅在家里叫外卖.他常吃的一家餐馆一共有N道菜品,价格分别是A1, A2, ... AN元.并且如果消费总计满X元,还能享受优惠.小Ho是一个不薅羊毛不舒服斯基的人,他希望 ...

随机推荐

  1. Haproxy和Nginx负载均衡测试效果对比记录

    为了对比Hproxy和Nginx负载均衡的效果,分别在测试机上(以下实验都是在单机上测试的,即负载机器和后端机器都在一台机器上)做了这两个负载均衡环境,并各自抓包分析.下面说下这两种负载均衡环境下抓包 ...

  2. 测试网站页面网速的一个简单Python脚本

    无聊之余,下面分享一个Python小脚本:测试网站页面访问速度 [root@huanqiu ~]# vim pywww.py #!/usr/bin/python # coding: UTF-8 imp ...

  3. maven依赖的描述

    maven的坐标和依赖 坐标和依赖,主要涉及的就是pom文件的头部和<dependencies>标签部分(1)pom文件的头部 这里头部不是指pom文件的开头<project> ...

  4. #科委外文文献发现系统——导出word模板1.0

    ps:该篇文档由实验室ljg提供. Crowdsourcing 一.             技术简介 Crowdsourcing, a modern business term coined in ...

  5. Linux内核分析作业第八周

    进程的切换和系统的一般执行过程 一.进程调度的时机 中断处理过程(包括时钟中断.I/O中断.系统调用和异常)中,直接调用schedule(),或者返回用户态时根据need_resched标记调用sch ...

  6. text3

    GitHub地址https://github.com/gaodejian/gaodejian/blob/master/firework 课题研究的目的和意义 java编程语言在编程方面的具体应用,以及 ...

  7. mybatis逆向工程生成example的问题

    如果不想生成example,在 targetRuntime="MyBatis3" 处修改为  targetRuntime="MyBatis3Simple"  & ...

  8. 福州大学软件工程1816 | W班 作业成绩排名汇总

    评分链接 第一次作业--准备篇 第二次作业--个人项目实战 第三次作业--原型设计(结对第一次) 第四次作业--团队展示(团队) 第五次作业--项目选题报告(团队) 第六次作业--结对第2次作业--W ...

  9. jmeter创建数据库测试计划

    这个例子要:创建50个用户发送2个sql请求到数据库服务器, 也可设置用户重复执行100次,这样总的请求数=50*2*100 用到以下元素:thread group / jdbc request / ...

  10. 构建squid代理服务器

    基本概念 本文使用squid代理服务 软件介绍:百度百科 作为应用层的代理服务软件,Squid主要提供缓存加速.应用层过滤控制的功能: 工作机制:缓存网页对象,减少重复请求(HTTP代理的缓存加速对象 ...