您的位置:首页 > 其它

2012-2013 ACM-ICPC East Central North America Regional Contest (ECNA 2012)

2015-05-21 10:32 756 查看

训练感想

从今天开始,HIT_Foodie队就进入了系统训练的阶段,也开始为
上海大都会站
的比赛开始做准备了。队里三个人,我最弱! 所以以后我一定会好好训练,争取不拖两位大爷的后腿!

今天的题难度就是regional难度,训练的时候因为一个
浮点误差
的问题调试了很长时间。所以接下来总结一番,并且补上没做的题。

题目分析

先把题目放出来,然后是Gym地址。

A题 Babs’ Box Boutique

题意

给n(n<10)个长方体,把这些长方体按照顺序叠放起来,注意叠放的时候,接触面要严格保持小于关系,
(x <= a && y <= b) || (x <= b && y <= a)


直接搜索即可,tomriddly同学貌似忘了回溯,WA了一发。

/* written by tomriddly */
#include <bits/stdc++.h>

using namespace std;
int n;
struct Box
{
int b[3];
inline void get()
{
scanf("%d%d%d", b + 0, b + 1, b + 2);
}
}a[11];
int ans = 0;
bool vis[11];

inline bool check(const int &x, const int &y, const int &a, const int &b)
{
return (x <= a && y <= b) || (x <= b && y <= a);
}

inline void dfs(const Box &last, const int &x, const int &y, const int &depth)
{
if (ans < depth)
ans = depth;
for (int i = 1; i <= n; i++)
if (!vis[i])
{
vis[i] = true;
if (check(a[i].b[0], a[i].b[1], last.b[x], last.b[y]))
dfs(a[i], 0, 1, depth + 1);
if (check(a[i].b[0], a[i].b[2], last.b[x], last.b[y]))
dfs(a[i], 0, 2, depth + 1);
if (check(a[i].b[2], a[i].b[1], last.b[x], last.b[y]))
dfs(a[i], 2, 1, depth + 1);
vis[i] = false;
}
}

int main()
{
int cas = 0;
while (~scanf("%d", &n) && n)
{
ans = 0;
memset(vis, false, sizeof(vis));
for (int i = 1; i <= n; i++)
a[i].get();
for (int i = 1; i <= n; i++)
{
vis[i] = true;
dfs(a[i], 0, 1, 1);
dfs(a[i], 0, 2, 1);
dfs(a[i], 2, 1, 1);
vis[i] = false;
}
printf("Case %d: %d\n", ++cas, ans);
}
return 0;
}


B题 Flash Mob

题意

给一些点的坐标,求出到这些点的
曼哈顿距离
之和最小,且横竖坐标均最小的点的坐标及他们的曼哈顿距离之和

把给的x坐标排序,y坐标排序,各自选取中位数即可。注意
偶数个的时候选取n/2的值


/* written by jiefangxuanyan */
#include <cstdio>
#include <algorithm>
const int N=1100;
int xs
,ys
;
int main(){
int cn=0;
while(true){
int n;
scanf("%d",&n);
if(!n){
return 0;
}
for(int i=0;i<n;i++){
scanf("%d%d",xs+i,ys+i);
}
std::sort(xs,xs+n);
std::sort(ys,ys+n);
int xm=xs[(n-1)/2],ym=ys[(n-1)/2];
int s=0;
for(int i=0;i<n;i++){
s+=std::abs(xs[i]-xm);
}
for(int i=0;i<n;i++){
s+=std::abs(ys[i]-ym);
}
printf("Case %d: (%d,%d) %d\n",++cn,xm,ym,s);
}
}


C题 Hexagon Perplexagon

题意

这题有点恶心,题意就不解释了,算是一个搜索。

我们直接用
next_permutation()
居然 TLE 了

然后安神展开了一番剪枝,终于过了。

#include <cstdio>
#include <algorithm>
int in[10][10];
void rotate(int *h,int tgt,int pos){
for(int i=0;i<6;i++){
if(h[i]==tgt){
int tmp[10];
for(int j=0;j<6;j++){
tmp[(pos+j)%6]=h[(i+j)%6];
}
for(int j=0;j<6;j++){
h[j]=tmp[j];
}
return;
}
}
}
/*bool validate(const int *put){
rotate(in[put[0]],1,0);
for(int i=0;i<6;i++){
rotate(in[put[i+1]],in[put[0]][i],(i+3)%6);
}
for(int i=0;i<6;i++){
if(in[put[i+1]][(i+2)%6]!=in[put[(i+1)%6+1]][(i+5)%6]){
return false;
}
}
return true;
}*/
bool dfs(int *perm,int pos){
if(pos==1){
rotate(in[perm[0]],1,0);
} else if(pos>1){
rotate(in[perm[pos-1]],in[perm[0]][pos-2],(pos+1)%6);
if(pos>2&&in[perm[pos-1]][(pos+2)%6]!=in[perm[pos-2]][(pos+5)%6]){
return false;
}
}
if(pos==7){
return in[perm[1]][4]==in[perm[6]][1];
}
for(int i=pos;i<7;i++){
std::swap(perm[pos],perm[i]);
if(dfs(perm,pos+1)){
return true;
}
}
for(int i=pos;i+1<7;i++){
std::swap(perm[i],perm[i+1]);
}
return false;
}
int main(){
int cn;
scanf("%d",&cn);
for(int ci=1;ci<=cn;ci++){
for(int i=0;i<7;i++){
for(int j=0;j<6;j++){
scanf("%d",in[i]+j);
}
}
int perm[10]/*={3,0,5,6,1,4,2}*/;
for(int i=0;i<7;i++){
perm[i]=i;
}
printf("Case %d:",ci);
/*do{
if(validate(perm)){
goto lblSucc;
}
} while(std::next_permutation(perm,perm+7));*/
if(dfs(perm,0)){
for(int i=0;i<7;i++){
printf(" %d",perm[i]);
}
putchar('\n');
} else{
puts(" No solution");
}
}
return 0;
}


D题 I’ve Got Your Back(gammon)

题意

给一个六位的序列,要求各位之和加起来是15。这样的序列一共有
15504
个。

把这些序列按照字典序排序,给定两种查询。1是查询第几个序列是什么,2是查询某个序列的序号是多少。

直接生成所有的序列,用map映射一下就可以了。

/* written by tomriddly */
#include <bits/stdc++.h>

using namespace std;
struct Fuck
{
int a[7];
inline friend bool operator <(const Fuck &x, const Fuck &y)
{
for (int i = 1; i <= 6; i++)
if (x.a[i] != y.a[i])
return x.a[i] < y.a[i];
return false;
}
inline friend bool operator ==(const Fuck &x, const Fuck &y)
{
for (int i = 1; i <= 6; i++)
if (x.a[i] != y.a[i])
return false;
return true;
}
}a[15555];
int tmp[7], cnt = 0, n;
char cmd[11];
map<Fuck, int> r;
inline void dfs(int depth, int presum)
{
if (depth == 6)
{
int sum = 0;
for (int i = 1; i <= 6; i++)
sum += tmp[i];
if (sum == 15)
{
for (int i = 1; i <= 6; i++)
a[cnt].a[i] = tmp[i];
cnt++;
}
return ;
}
for (int i = 0; i <= 15 - presum; i++)
{
tmp[depth + 1] = i;
dfs(depth + 1, presum + i);
}
}
int main()
{
int cas = 0;
dfs(0, 0);
//cout << cnt << endl;
sort(a, a + cnt);
/*
for (int i = 0; i < cnt; i++)
{
for (int j = 1; j <= 6; j++)
{
printf("%d%c", a[i].a[j], j == 6 ? '\n' : ' ');
}
system("pause");
}
*/
for (int i = 0; i < cnt; i++)
r[a[i]] = i;
while (~scanf("%s", cmd) && cmd[0] != 'e')
{
if (cmd[0] == 'm')
{
for (int i = 1; i <= 6; i++)
scanf("%d", &a[15550].a[i]);
printf("Case %d: %d\n", ++cas, r[a[15550]]);
}
else
{
int x;
scanf("%d", &x);
printf("Case %d:", ++cas);
for (int i = 1; i <= 6; i++)
printf(" %d", a[x].a[i]);
putchar('\n');
}
}
return 0;
}


E题 Parencedence!

占坑,会了在写。

应该是个对抗搜索,代码没时间写了。

F题 Road Series

先占着坑,等我看明白了再写。。。

/* written by jiefangxuanyan */
#include <cstdio>
#include <cstring>
#include <algorithm>
const int LEN=1100,MAXN=100000000;
char in[LEN];
int storage[LEN*10];
bool has[MAXN];
int main(){
int cn;
scanf("%d",&cn);
for(int ci=1;ci<=cn;ci++){
int n,w;
scanf("%d%d ",&n,&w);
int pos=1;
memset(has,0,sizeof(has));
has[0]=true;
int maxSeen=0;
for(int i=0;i<n;i++){
gets(in);
int cnt=0;
for(char *p=in;*p;p++){
int cur=0,i=0;
while(true){
storage[cnt++]=cur;
if(cur<MAXN&&'0'<=p[i]&&p[i]<='9'){
cur=cur*10+p[i]-'0';
i++;
} else{
break;
}
}
}
std::sort(storage,storage+cnt);
for(int i=0;i<cnt;i++){
if(storage[i]<pos+w){
maxSeen=std::max(storage[i],maxSeen);
has[storage[i]]=true;
while(has[pos]){
pos++;
}
}
}
}
printf("Case %d: %d %d\n",ci,pos-1,maxSeen);
}
return 0;
}


G题 Show Me the Money

题意

着重讲一下这道题。我们一上来就用了分数类,希望能够避免坑爹的浮点数误差。但是没有想到,使用
long long
竟然爆了。。。

没有办法,我们改成
double
,但是还是WA了。经过一番思想斗争,我们决定把代码改成java高精度!可惜的是,这回不是WA了,而是 TLE。。。

挣扎了许久,这道题我们差不多纠结了两个小时。最后还是没招,看了题解。

又TM是
ceil()
的时候加干扰。。。实在是太鬼畜了。。。

/* written by tomriddly */
#include <bits/stdc++.h>
using namespace std;

inline long long gcd(const long long &x, const long long &y)
{
return !y ? x : gcd(y, x % y);
}
/*
struct Fenshu
{
long long fenzi, fenmu;
inline Fenshu() {}
inline Fenshu(const long long &fenzi, const long long &fenmu):fenzi(fenzi), fenmu(fenmu) {}
inline friend bool operator <(const Fenshu &x, const Fenshu &y)
{
long long tongfen = gcd(x.fenmu, y.fenmu);
return x.fenzi * (x.fenmu / tongfen) < y.fenzi * (y.fenmu / tongfen);
}
inline friend Fenshu operator *(const Fenshu &x, const Fenshu &y)
{
long long fenzi = x.fenzi * y.fenzi, fenmu = x.fenmu * y.fenmu, tongfen = gcd(fenzi, fenmu);
return Fenshu(fenzi / tongfen, fenmu / tongfen);
}
}*/
typedef long double Fenshu;
long double f[11][11];
map<string, int> num;
int n;
int main()
{
ios::sync_with_stdio(false);
int cas = 0;
while (cin >> n && n)
{
num.clear();
int n1, n2;
string name1, name2;
int cnt = 0;
memset(f, 0, sizeof(f));
for (int i = 1; i <= n; i++)
{
cin >> n1 >> name1 >> name2 >> n2 >> name2;
if (num.find(name1) == num.end())
num[name1] = ++cnt;
if (num.find(name2) == num.end())
num[name2] = ++cnt;
int u = num[name1], v = num[name2];
Fenshu v1 = (long double)n2 / n1, v2 = (long double)n1 / n2;
if (f[u][v] <= 1e-14 || v1 < f[u][v])
f[u][v] = v1;
if (f[v][u] <= 1e-14 || v2 < f[v][u])
f[v][u] = v2;
}
//cout << cnt << endl;
int need;
string needname;
for (int k = 1; k <= cnt; k++)
for (int i = 1; i <= cnt; i++)
for (int j = 1; j <= cnt; j++)
{
if (f[i][k] <= 1e-14 || f[k][j] <= 1e-14)
continue;
Fenshu tmp = f[i][k] * f[k][j];
if (f[i][j] <= 1e-14 || tmp < f[i][j])
f[i][j] = tmp;
//cout << tmp << endl;
}
cin >> need >> needname;
int t = num[needname];
double ans = DBL_MAX;
int ansi;
long long fff;
for (int i = 1; i <= cnt; i++)
if (i != t && f[i][t] >= 1e-14)
{
long long tmp = (long long)ceill((long double)need / f[i][t] - 1e-8);
if (tmp > 100000)
continue;
double kui = fabs((long double)tmp / f[t][i] - need);
//cout << tmp << " " << i << ' ' << kui <<  endl;
if (ans > kui)
ans = kui, ansi = i, fff = tmp;
}
cout << "Case " << (++cas) << ": ";
for (map<string, int>::iterator p = num.begin(); p != num.end(); p++)
if (p->second == ansi)
{
cout << fff << " " << p->first << endl;
break;
}
}
}
/*
4
23 a = 17 b
16 c = 29 e
5 b = 14 e
1 d = 7 f
100 a
*/


H题 Sofa, So Good

会了再补上。。

I题 Town Square

题意

只看懂了题意。。给四个圆,半径都是5。。求一个最小的正方形,与他们四个圆都相切。。

还不会,等会了再来补上。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐