POJ 刷水(2)

这一篇的看点PKU1088、PKU1012。

PKU1008

分析:先按H历法算出总天数,再模T历法一年的天数的到T历法的年,

但T历法没月的概念,只是两个独立循环的组合,所以分别模20和13就能得到结果。

数据4. uayet 259应输出13 ahau 364。

代码
#include<stdio.h>
#include
<string.h>
int main()
{
char HM[19][10]={"pop", "no", "zip", "zotz", "tzec", "xul", "yoxkin",
"mol", "chen", "yax", "zac", "ceh", "mac", "kankin", "muan", "pax",
"koyab", "cumhu", "uayet"};
char TD[20][10]={"imix", "ik", "akbal", "kan", "chicchan", "cimi", "manik",
"lamat", "muluk", "ok", "chuen", "eb", "ben", "ix", "mem", "cib",
"caban", "eznab", "canac", "ahau"};
int i,j,n,Hyear,Hday,Tyear,tds;//tds是totaldays总天数
char Hmonth[10];
scanf(
"%d",&n);
printf(
"%d\n",n);
for(i=1;i<=n;i++)
{
tds
=0;
scanf(
"%d.%s %d",&Hday,Hmonth,&Hyear);
tds
+=365*Hyear+Hday;//按Haab历计算总天数
for(j=0;j<19;j++) //循环累加求一年里的天数
if(strcmp(HM[j],Hmonth)==0)
{
tds
+=j*20;
break;
}
Tyear
=tds/260;
tds
=tds%260;
printf(
"%d %s %d\n",tds%13+1,TD[tds%20],Tyear);//要加1
}
return 0;
}

 

PKU1163

分析:这是老师给的动态规划课件里面的一道例题,即数塔问题。和HDU2084题目一样,要是不懂题意可以去那里看中文。动态规划思想,从数塔下面往上面动态最优求和。

代码
#include<stdio.h>
int ma(int n,int m)
{
return n>m?n:m;
}
int main()
{
int n,a[102][102];
int i,j;
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<n;i++)
for(j=0;j<=i;j++)
scanf(
"%d",&a[i][j]);
for(i=n-2;i>=0;i--)
for(j=0;j<=i;j++)
a[i][j]
=ma(a[i][j]+a[i+1][j],a[i][j]+a[i+1][j+1]);
printf(
"%d\n",a[0][0]);
}
return 0;
}

 

PKU1088

求一个二维数组的最长递减序列的长度(一个点滑向上下左右相邻四个点之一),对每个点都作为起点搜一次。

如果用常规的广度优先搜索方法,重复的子问题太多。对于其中的每个值都要广度搜索一次,找出其能够搜出的最大搜索次数,然后找出所有点的最大搜索次数的最大值。

用记忆化搜索,添加一个二维表,记忆每个搜索过的点的最大递归次数,当下一次搜索到该点时,就可以直接从二维表中直接取出来用就可以了。

代码
#include<stdio.h>
#include
<string.h>
int r,c,map[102][102],f[102][102];
int dir[4][2]={{-1,0},{1,0},{0,1},{0,-1}};
bool ok(int x,int y)
{
return (x>=0 && x<r && y>=0 && y<c);
}
int find(int x,int y)
{
int i,fx,fy;
if(f[x][y]>0)
return f[x][y];
for(i=0;i<4;i++)
{
fx
=x+dir[i][0];
fy
=y+dir[i][1];
if(ok(fx,fy) && map[x][y]>map[fx][fy] && f[x][y]<find(fx,fy)+1)
f[x][y]
=find(fx,fy)+1;
}
return f[x][y];
}
int main()
{
int i,j,mediate,max;
while(scanf("%d%d",&r,&c)!=EOF)
{
for(i=0;i<r;i++)
for(j=0;j<c;j++)
scanf(
"%d",&map[i][j]);
memset(f,
0,sizeof(f));
max
=0;
for(i=0;i<r;i++)
for(j=0;j<c;j++)
{
mediate
=find(i,j);
if(max<mediate)
max
=mediate;
}
printf(
"%d\n",max+1);
}
return 0;
}

 

PKU2027

太水了,不多说了。

PKU1012

约瑟夫问题,我先查到了位置坐标公式:f[i]=(f[i-1]+m-1)%(n-i+1);然后看了discuss上《总结三点》帖子

1.要kill的人的位置公式p=(p+m-1)%rest+1

2.kill的位置<k就break,此时剩下的人rest等于k就成功

3.m不要递增,m是k+1的整数倍或者k+1的整数倍加1,这样会提高不少

第三点不明白,就让m递增了,超时。

后又查找第三点的原因,在ericxieforever的专栏找到了答案。

另外这一题要把结果打表后再输出,不然还会超时。

分析:先引入Joseph递推公式,设有n个人(0,...,n-1),数m,则第i轮出局的人为f(i)=(f(i-1)+m-1)%(n-i+1),f(0)=0;

依次我们可以来做测试,只要前k轮中只要有一次f(i)<k则此m不符合题意。

接下来我们考察一下只剩下k+1个人时候情况,那么依题意则这一轮出局的人要么在上一轮出局人的左边,要么就在右边,则必有m%(k+1)==0或1

代码
#include<stdio.h>
int main()
{
int k,m,i;
int f,t,a[14];
for(k=1;k<14;k++){
t
=0;
for(m=1; ;m+=((t++)%2?1:k)){
f
=0;
for(i=1; ;i++){
f
=(f+m-1)%(2*k-i+1);
if(f<k){
break;
}
}
if(i==k+1)
break;
}
a[k]
=m;
}
while(scanf("%d",&k),k)
printf(
"%d\n",a[k]);
return 0;
}

 

PKU1046 

对16以后的每个点从16个三维坐标中找距离最近的点形成映射。

挺简单,就贴代码了。

代码
#include<stdio.h>
#include
<math.h>
const int SIZE = 100;
int pos[100];//记录对应的最小值所在位置
struct RGB
{
int red,green,blue;
}colors[SIZE];
double distance(RGB* color1,RGB* color2)
{
double r = color1->red-color2->red;
double g = color1->green-color2->green;
double b = color1->blue-color2->blue;
return sqrt(r*r+g*g+b*b);
}
int main(void)
{
double dist,min;
int count=0, r,g,b,i,j,k;
while (scanf("%d%d%d",&r,&g,&b),r+g+b!=-3)
{
colors[count].red
= r;
colors[count].green
= g;
colors[count].blue
= b;
count
++;
}
k
=0;
for (i=16;i<count;++i)
{
min
= 0xfffffff;
for (j=0;j<16;++j)
{
dist
= distance(&colors[i],&colors[j]);
if (dist<min)
{
min
= dist;
pos[k]
= j;
}
}
k
++;
}
for (i=16,k=0;i<count;++i,++k)
{
printf(
"(%d,%d,%d) maps to (%d,%d,%d)\n",colors[i].red,colors[i].green,colors[i].blue,colors[pos[k]].red,colors[pos[k]].green,colors[pos[k]].blue);
}
return 0;
}

PKU1050

二维数组找子矩形的最大和。(枚举+DP)

i从0到n-1循环,j从i到n-1循环,对i和j所指的行和其中间的行求和,得到一个一维数组,每次都求出这个一维数组的最大连续子序列,最大值即为结果。

代码
#include<stdio.h>
#include
<string.h>
int map[100][100],n,temp[100],maxNum;
void findmaxNum()
{
int i,m = 0;
for(i=0;i<n;i++)
{
if(m>=0)
m
+= temp[i];
else
m
= temp[i];
if(m>maxNum)
maxNum
= m;
}
}
int main()
{
int i,j,k;
scanf(
"%d",&n);
maxNum
= -222222222;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf(
"%d",&map[i][j]);
for(i=0;i<n;i++)
{
memset(temp,
0,sizeof(temp));
for(j=i;j<n;j++)
{
for(k=0;k<n;k++)
temp[k]
+= map[j][k];
findmaxNum();
}
}
printf(
"%d\n",maxNum);
return 0;
}

PKU1207

暴力0MS过的

代码
#include<stdio.h>
int len(int a)
{
int t=1;
while(a!=1)
{
if(a%2)
a
=3*a+1;
else
a
/=2;
t
++;
}
return t;
}
int main()
{
int i,a,b,aa,bb,t,max;
while(scanf("%d%d",&a,&b)!=EOF)
{
aa
=a; bb=b;
if(a>b)
{
t
=a; a=b; b=t;
}
max
=0;
for(i=a;i<=b;i++)
{
t
=len(i);
if(max<t)
max
=t;
}
printf(
"%d %d %d\n",aa,bb,max);
}
return 0;
}

 

posted @ 2010-07-22 20:29  孟起  阅读(331)  评论(0编辑  收藏  举报