您的位置:首页 > 编程语言 > Java开发

2011 Spring Trainning Contest SLPC

2012-02-14 17:15 78 查看
额,几天没来博客了,得写点东西……

先说上周六的这场比赛。

又是水过了简单题目,稍微难的就没有想出,然后其他题目又懒得看了……

这其实是学长挂的组队赛的,题目不算很难(因为我总感觉我能做出来的就是简单题目,事实上一直如此),大部分单个人参赛的都A掉了4、5道题目,而HIT_IF、HITDPS则A掉了11道,差一道AK……两个好牛的队伍啊……

先将我A掉的题目的题解写一下:(有点废话,没A掉怎么会写题解)

HOJ 2999 AAAAHH!Overbooked!

大水题第一:给了n条线段(开区间),求有木有两条线段有重叠部分。

排序,然后检查即可。

#include <iostream>
#define N 110
using namespace std;
struct data
{
int start,end;
void input()
{
int st1,st2,en1,en2;
scanf("%d:%d-%d:%d", &st1, &st2, &en1, &en2);
start=st1*100+st2;
end=en1*100+en2;
}
bool operator< (const data b)const
{
return start<b.start;
}
}p
;
int main()
{
int n,i;
bool flag;
while(scanf("%d",&n),n)
{
for(i=0;i<n;i++)
p[i].input();
sort(p,p+n);
flag=true;
for(i=0;flag&&i<n-1;i++)
if(p[i+1].start<p[i].end)flag=false;
if(!flag)puts("conflict");
else puts("no conflict");
}
return 0;
}


HOJ 3000 Betting Sets

额,这道题是大水题第二,凭感觉这么做,但不知道具体的证明。

给了n行m列数,对每列数进行排序,使得每行数相乘后的和最大。然后我就都按从小到大排了,应该有个证明最大数乘最大数、第二大乘第二大……最小乘最小,最终的和最大。

#include <iostream>
#define N 100
using namespace std;
double a

;
int main()
{
int n,m,i,j;
double ans,p;
while(scanf("%d %d",&n,&m),n||m)
{
ans=0;
for(i=0;i<n ;i++)
for(j=0;j<m;j++)
scanf("%lf",a[j]+i);
for(i=0;i<m;i++)
sort(a[i],a[i]+n);
for(i=0;i<n;i++)
{
p=1;
for(j=0;j<m;j++)
p*=a[j][i];
ans+=p;
}
printf("%.4lf\n",ans);
}
return 0;
}


HOJ 3001 Counting Pixels

大坑爹题第一。。。

坑爹啊。。。。

很朴素的横坐标逐一检查即可A掉,不过数据不厚道,竟然不是以3个0结尾,所以搞得我一直超时,想各种优化,差点就打表了。。。后来还是交了一个O(sqrt(n))的算法A掉了。

#include <iostream>
#include <math .h>
using namespace std;

int main()
{
long long x,y,r,p,k,i;
while(scanf("%lld %lld %lld",&x,&y,&r)==3&&(x||y||r))
{
if(r==1)
{
puts("4");
continue;
}
k=0;
for(i=r-1;i>0;i--)
{
p=(long long)ceil(sqrt(r*r-i*i));
if(p< =i)k+=p;
if(p>=i)
{
k< <=1;
k+=p*p;
break;
}
}
k*=4;
printf("%lld\n",k);
}
return 0;
}


HOJ 3002 Matryoshka Dolls

大水题第三。。。。 题目大概意思是关于套娃的。。。。一层套一层。。。 做法就是求出相同型号的个数的最大值。

#include <iostream>
#define N 100100
using namespace std;
int a
;
int main()
{
int n,i,tot,ans;
while(scanf("%d",&n),n)
{
ans=0;
tot=1;
for(i=0;i<n ;i++)
scanf("%d",a+i);
sort(a,a+n);
for(i=1;i<n;i++)
{
if(a[i]==a[i-1])tot++;
else
{
if(tot>ans)ans=tot;
tot=1;
}
}
if(tot>ans)ans=tot;
printf("%d\n",ans);
}
return 0;
}


HOJ 3003 Equilateral Dominoes

这个题还是不错。

给了n个菱形,每个菱形都是由2个带有数字的等边三角形组成,选取一部分拼接到一起,使得相邻菱形相邻的三角形数字相同。求最大的公共边。

n的范围很小,只有6.所以算法的复杂度可以很大,关键是不好下手写这个搜索。先写了1个任意填充,最后检查的,以WA或者TLE宣告失败,然后重写了个边检查边放的,结果太杂乱,运行结果错误,也不容易debug,而宣告失败。今天再次改变策略,不管是否会重复搜索,都搜索一下,最终一0.03s宣告AC。。。

代码很长很夸张。。。。

#include <stdio .h>
const int M = 100;
const int N = 6;
int ans , n ;
struct data
{
int right, left;
bool used;
void input()
{
scanf("%d %d", &right, &left);
used = false;
}
} p[ N ];
struct data_map
{
int x, y, color, is_to_set, tot_filled;
bool filled;
data_map& neighbor( int );
void init( int i, int j )
{
x = i;
y = j;
filled = false;
}
bool check()
{
is_to_set = -1;
tot_filled = 0;
for( int i = 0 ; i < 3 ; i ++ )
{
if( neighbor( i ).filled )
{
tot_filled ++;
if( is_to_set == -1 ) is_to_set = neighbor( i ).color;
else if( is_to_set != neighbor( i ).color ) return false;
}
}
return true;
}
bool check_color( int col )
{
if( is_to_set == -1 ) return true;
return col == is_to_set;
}
void inque( int col ,int tail );
void outque()
{
filled = false;
color  = 0;
}
} map[ M ][ M ], *que[ M * M ];

data_map& data_map::neighbor(int k)
{
if( k == 0 ) return map[ x ][ y - 1 ];
if( k == 1 ) return map[ x ][ y + 1 ];
if( ( x ^ y ) & 1 ) return map[ x + 1 ][ y ];
return map[ x - 1 ][ y ];
}
void data_map::inque( int col ,int tail )
{
filled = true;
color = col;
que[ tail ] = this;
}
void dfs(int tail, int num)
{
if( num > ans )
{
ans = num;/*
for( int i = 0 ; i < 40 ; i ++ )
for( int j = 0 ; j < 40 ; j ++ )
{
printf("%d " , map[ i ][ j ].color);
if( j == 39 ) puts("");
}
puts("");*/
}
for( int i = 0 ; i < n ; i ++ )
{
if( !p[ i ].used )
{
for( int j = 0 ; j < tail ; j ++ )
{
data_map &pos = *que[ j ];
if( pos.color == p[ i ].right || pos.color == p[ i ].left )
{
for( int k = 0 ; k < 3 ; k ++ )
{
data_map &new_pos = pos.neighbor( k );
if( !new_pos.filled && new_pos.check() )
{
for( int l = 0 ; l < 3 ; l ++ )
{
data_map &neigh = new_pos.neighbor( l );
if( !neigh.filled && neigh.check() )
{
if( new_pos.check_color( p[ i ].right ) && neigh.check_color( p[ i ].left ) )
{
new_pos.inque( p [ i ].right , tail );
neigh.inque( p[ i ].left , tail + 1);
p[ i ].used = true;

dfs( tail + 2 , new_pos.tot_filled + neigh.tot_filled + num );

p[ i ].used = false;
new_pos.outque();
neigh.outque();
}
else if(new_pos.check_color( p[ i ].left ) && neigh.check_color( p[ i ].right ) )
{
new_pos.inque( p [ i ].left , tail );
neigh.inque( p[ i ].right , tail + 1);
p[ i ].used = true;

dfs( tail + 2 , new_pos.tot_filled + neigh.tot_filled + num );

p[ i ].used = false;
new_pos.outque();
neigh.outque();
}
}
}
}
}
}
}
}
}
}                         //        十个括号套着呢啊,有木有啊。。。。
int main()
{
while( scanf("%d", &n ), n )
{
for( int i = 0 ; i < n ; i ++ )
{
p[ i ].input();
}
for( int i = 0 ; i < M ; i ++ )
for( int j = 0 ; j < M ; j ++ )
map[ i ][ j ].init( i , j );
ans = 0;
for( int i = 0 ; i < n ; i ++ )
{
p[ i ].used = true;
map[ 20 ][ 20 ].inque( p[ i ].right , 0 );
map[ 20 ][ 21 ].inque( p[ i ].left , 1 );
dfs( 2 , 0 );
map[ 20 ][ 20 ].outque();
map[ 20 ][ 21 ].outque();
p[ i ].used = false;
}
printf("%d\n", ans);
}
return 0;
}


HOJ 3004 Four Gate Push

二维背包问题,题目还是拐了下弯,你还得先除以25、50,然后再背包,这样内存才够。。。

#include <iostream>
#define M 2100
#define G 1100
using namespace std;
int f[M][G];
int main()
{
int m,g,z,s,e,i,j;
while(scanf("%d %d %d %d %d",&m,&g,&z,&s,&e),m||g||z||s||e)
{
memset(f,0,sizeof(f));
m/=25;
g/=50;
for(i=4;i< =m;i++)
for(j=0;j<=g;j++)
f[i][j]=max(f[i][j],f[i-4][j]+z);
for(i=5;i<=m;i++)
for(j=1;j<=g;j++)
f[i][j]=max(f[i][j],f[i-5][j-1]+s);
for(i=2;i<=m;i++)
for(j=2;j<=g;j++)
f[i][j]=max(f[i][j],f[i-2][j-2]+e);
printf("%d\n",f[m][g]);
}
return 0;
}


水了,水了,这不是正解。正解是枚举三个的量。。。

#include <iostream>

using namespace std;

int main()
{
int n, g, z, s, e, i, j, k;
while(scanf("%d %d %d %d %d",&n, &g, &z, &s, &e ), n | g | z | s | e )
{
int ans = 0;
for( k = 0 ; k * 50 < = n && k * 100 <= g; k ++ )
for( j = 0 ; j * 125 + k * 50 <= n && j * 50 + k * 100 <= g ; j ++ )
{
i = ( n - j * 125 - k * 50 ) / 100;
ans = max( ans , i * z + j * s + k * e );
}
printf("%d\n",ans);
}
return 0;
}


HOJ 3005 Game Rigging

知道一部分人对决的胜负情况,能否让某些人中有一个人取胜。

DFS 啊,你手下败将能打败的就算败给你啦。。。就看你能搞定的人能不能搞定其他人拉。。有木有啊。。。。

池子法啊,有木有啊。。。。

#include <iostream>
#define N 100100
#define M 100100
#define K N
using namespace std;
int visit
,tot;
int fri[K];
struct edge_data
{
int v;
edge_data*next;
}*adj
,edge[M];
void pushedge(int a,int b)
{
edge[tot].v=b;
edge[tot].next=adj[a];
adj[a]=&edge[tot++];
}
void dfs(int k)
{
visit[k]=1;
edge_data *temp=adj[k];
while(temp)
{
if(!visit[temp->v])dfs(temp->v);
temp=temp->next;
}
}
int main()
{
int n,m,k,i,a,b;
while(scanf("%d %d %d",&n,&k,&m),n||m||k)
{
memset(visit,0,sizeof(visit));
memset(adj,0,sizeof(adj));
tot=0;
for(i=0;i<k ;i++)
scanf("%d",fri+i);
for(i=0;i<m;i++)
{
scanf("%d %d",&a,&b);
pushedge(a,b);
}
for(i=0;i<k;i++)
if(!visit[fri[i]])dfs(fri[i]);
for(i=0;i<n;i++)
if(!visit[i+1])break;
if(i==n)puts("yes");
else puts("no");
}
return 0;
}


HOJ 3006 Highway Construction

当时没看懂题啊,原来是求数的直径啊,大水题啊,有木有啊。。。

随便找一点作为根进行深搜,最远的节点再作为根,再深搜,这次又得到一个最远节点,两次最远节点路上的点就是特么要修的高速公路啊。。。然后从高速公路上每个点向非高速公路上的点深搜,找一个最远距离就over啦。。。。

#include <stdio .h>
#include <string .h>
const int N = 100100;
struct data_edge
{
int v,w;
data_edge *next;
}*adj[ N ], edge[ N < < 1 ];
int visit[ N ], online[ N ], father[ N ];
int n, maxdeep, findk, tot_edge;
void push_edge( int u,int v,int w)
{
edge[ tot_edge ].v = v;
edge[ tot_edge ].w = w;
edge[ tot_edge ].next = adj[ u ];
adj[ u ] = &edge[ tot_edge ++ ];
}
void init()
{
memset( adj , 0 , sizeof( adj ) );
tot_edge = 0;
for( int i = 0 ; i < n - 1 ; i ++ )
{
int a,b,w;
scanf("%d %d %d", &a, &b, &w);
push_edge(a, b, w);
push_edge(b, a, w);
}
}
void dfs(int k, int deep)
{
visit[ k ] = 1;
data_edge *temp = adj[ k ];
while( temp )
{
if( !visit[ temp->v ])
{
father[ temp->v ] = k;
dfs( temp->v , deep + temp->w);
}
temp = temp->next;
}
if( deep > maxdeep)
{
maxdeep = deep;
findk = k;
}
}
void solve()
{
maxdeep = 0;
memset(visit , 0 ,sizeof( visit ));
dfs( 1 , 0 );
memset(visit , 0 ,sizeof( visit ));
int firstk = findk;
maxdeep = 0;
dfs( findk , 0 );
memset(visit , 0 ,sizeof( visit ));
memset(online , 0 ,sizeof( online ));
int lastk = findk;
while( lastk != firstk )
{
visit[ lastk ] = 1;
online[ lastk ] = 1;
lastk = father[ lastk ];
}
online[ lastk ] = 1;
visit[ lastk ] = 1;
maxdeep = 0;
for( int i = 1 ; i < = n ; i++ )
if( online[ i ] )
dfs( i , 0 );
printf("%d\n",maxdeep);
}
int main()
{
while(scanf("%d", &n) , n)
{
init();
solve();
}
return 0;
}


HOJ 3008 Matryoshka Dolls, Again

坑爹啊,上面某道题的加强版啊,然后就变成匹配啦。。。。当时还拿搜索做来着,超时啊。。。。后来用匈牙利算法。。。强大啊。。。

算是一道难题吧。。。。

#include <iostream>
#define N 510
using namespace std;
int f[ N ], ans, n, tot_edge, visit[ N ], match[ N ];
struct data
{
int x,y,z;
void input()
{
scanf("%d %d %d",&x,&y,&z);
}
bool operator< (data b)
{
return x<b.x&&y<b.y&&z<b.z;
}
}p
;
struct edge_data
{
int v;
edge_data*next;
}edge[ N * N ], *adj[ N ];

void push_edge(int u,int v)
{
edge[ tot_edge ].v = v;
edge[ tot_edge ].next = adj[ u ];
adj[ u ] = &edge[ tot_edge++ ];
}
void input()
{
tot_edge = 0;
memset( adj , 0 , sizeof( adj ) );
int i,j;
for ( i = 0 ; i < n ; i++)
p[ i ].input();
for ( i = 0 ; i < n ; i++)
for ( j = 0 ; j < n ; j++)
if (p[ i ] < p[ j ]) push_edge( i, j );
}
bool dfs( int k )
{
edge_data *temp=adj[ k ];
while( temp )
{
if( !visit[ temp->v ])
{
visit[ temp->v ] = 1;
if( match[ temp->v ] == -1 || dfs( match[ temp-> v ] ) )
{
match[ temp->v ] = k;
return true;
}
}
temp = temp->next;
}
return false;
}
void solve()
{
int ans = 0;
memset( match , -1 , sizeof( match ) );
for ( int i = 0 ; i < n ; i++)
{
memset( visit , 0 , sizeof( visit ) );
if ( dfs( i ) ) ans++;
}
printf("%d\n", n - ans );
}
int main()
{
while (scanf("%d",&n),n)
{
input();
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐