题目整体不难,很多都可以暴力直接做,但是除去比赛时做出来的五道题之外剩下的代码量都比较高,写的比较艰难。
A:Babs' Box Boutique
题意是问怎么塞盒子可以塞的数量最多(只考虑底边符合,三边可以旋转)
因为n<=10,所以果断排序后DFS暴搜,简单过
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
using namespace std;
struct node
{
int a;
int b;
int c;
} s[1005];
int n;
int ans;
int used[1005];
void DFS(int ax,int ay,int k,int t)
{
if(t>ans)
{
ans=t;
}
for(int i=0; i<n; i++)
{
if(used[i]==0)
{
if(s[i].a>=ax&&s[i].b>=ay)
{
used[i]=1;
DFS(s[i].a,s[i].b,k+1,t+1);
used[i]=0;
}
else if(s[i].a>=ax&&s[i].c>=ay)
{
used[i]=1;
DFS(s[i].a,s[i].c,k+1,t+1);
used[i]=0;
}
else if(s[i].b>=ax&&s[i].c>=ay)
{
used[i]=1;
DFS(s[i].b,s[i].c,k+1,t+1);
used[i]=0;
}
}
}
}
int main()
{
int counter = 0;
while(scanf("%d",&n)!=EOF)
{
counter++;
if(n==0) break;
memset(used,0,sizeof(used));
int aa,bb,cc;
int t[4];
for(int i=0; i<n; i++)
{
for(int j=0; j<3; j++)
{
scanf("%d",&t[j]);
}
sort(t,t+3);
s[i].a=t[0];
s[i].b=t[1];
s[i].c=t[2];
}
ans=0;
DFS(0,0,0,0);
printf("Case %d: %d\n",counter,ans);
}
return 0;
}
B:Flash Mob
求离给出所有点的曼哈顿距离最近的点,因为是曼哈顿距离所以X,Y可以分开计算,并且最近的点必然在已有点中间,进一步能退出肯定是中间的点
这样子题目就很好写了。
我写的是狂搜,效率不是很高,回头改一下
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
using namespace std;
int n;
int x[1005],y[1005];
int sumx,sumy,weix,weiy,xx,xy;
bool cmp(int a,int b)
{
return a < b;
}
int main()
{
int counter = 0;
while(scanf("%d",&n) != EOF)
{
counter++;
if(n == 0) break;
for(int i=0;i<n;i++)
{
scanf("%d%d",&x[i],&y[i]);
}
sort(x,x+n,cmp);
sort(y,y+n,cmp);
sumx = 0;
sumy = 0;
weix = x[0];
weiy = y[0];
for(int i=0;i<n;i++)
{
sumx += abs(x[i] - weix);
sumy += abs(y[i] - weiy);
}
xx = sumx;
xy = sumy;
//cout<<x[0]<<' '<<y[0]<<endl;
//cout<<sumx<<' '<<sumy<<endl;
for(int i=1;i<n;i++)
{
xx = xx + (i) * (x[i] - x[i-1]) - (n - i) * (x[i] - x[i-1]);
xy = xy + (i) * (y[i] - y[i-1]) - (n - i) * (y[i] - y[i-1]);
//cout<<x[i]<<' '<<y[i]<<endl;
//cout<<xx<<' '<<xy<<endl;
if(xx < sumx)
{
sumx = xx;
weix = x[i];
}
if(xy < sumy)
{
sumy = xy;
weiy = y[i];
}
}
printf("Case %d: (%d,%d) %d\n",counter,weix,weiy,sumx+sumy);
}
}
C:Hexagon Perplexagon
给出七个正六边形,要求能凑出左边哪个造型(相邻边上的数字相同)
因为给出限定最上面哪个和中间的那个相邻的必须是1,所以计算量直接压缩到7!
在加上相邻边之间有规律(与中间相邻的数其前面一个数必然属于后一个六边形,后一个必然属于前一个六边形
所以if一下很快就出来了
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
using namespace std;
int s[20][20],f[20][20];
int k[20],l[20];
bool used[20];
bool usedans;
void dfs(int x)
{
for(int i=0; i<7;i++)
{
if(used[i] == false)
{
k[x]=i;
if(x==0)
{
l[0]=f[k[0]][1];
}
else
{
int t=s[k[0]][l[0]+x-1];
l[x]=f[k[x]][t];
if(x>1&&s[k[x-1]][l[x-1]+5]!=s[k[x]][l[x]+1])
{
continue;
}
if(x==6&&s[k[x]][l[x]+5]==s[k[1]][l[1]+1])
{
usedans=true;
}
}
used[i]=true;
if(x<6)
{
dfs(x+1);
}
used[i]=false;
if(usedans == true)
{
return ;
}
}
}
}
int main()
{
int T,counter = 0;
scanf("%d",&T);
while(T--)
{
counter++;
for(int i=0; i<7;i++)
{
for(int j=0; j<6;j++)
{
scanf("%d",&s[i][j]);
s[i][j+6]=s[i][j];
f[i][s[i][j]]=j;
}
}
usedans=false;
memset(used,false,sizeof(used));
dfs(0);
printf("Case %d:",counter);
if(usedans)
{
for(int i=0; i<=6;i++)
{
printf(" %d",k[i]);
}
printf("\n");
}
else
{
printf(" No solution\n");
}
}
return 0;
}
D:I've Got Your Back(gammon)
题目告诉我们不超过15504
那么就按照不超过15504打表
很快就过了
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
using namespace std;
int s[10][16000];
void get()
{
s[1][0] = s[2][0] = s[3][0] = s[4][0] = s[5][0] = 0;
s[6][0] = 15;
for(int i = 1; i < 15504; i++)
{
for(int j=1; j<=5; j++)
{
s[j][i] = s[j][i-1];
}
if(s[6][i-1] != 0)
{
s[6][i] = s[6][i-1] - 1;
s[5][i] = s[5][i-1] + 1;
}
else
{
int t = 5;
while(s[t][i-1] == 0)
{
t--;
}
s[t][i] = 0;
s[t-1][i] = s[t-1][i-1] + 1;
s[6][i] = s[t][i-1] - 1;
}
}
}
int main()
{
get();
char c;
int q[10];
int a,counter = 0;
while(scanf("%c",&c) != EOF)
{
if(c == 'e') break;
counter++;
printf("Case %d: ",counter);
if(c == 'm')
{
for(int i=1; i<=6; i++)
{
scanf("%d",&q[i]);
}
int w;
for(int i=0;i<15504;i++)
{
w = 0;
for(int j=1;j<=6;j++)
{
if(s[j][i] != q[j])
{
w = 1;
break;
}
}
if(w == 0)
{
printf("%d\n",i);
break;
}
}
}
if(c == 'u')
{
scanf("%d",&a);
printf("%d",s[1][a]);
for(int i=2;i<=6;i++)
{
printf(" %d",s[i][a]);
}
printf("\n");
}
getchar();
}
}
E:Parencedence!
题目略麻烦
求两个人对一个已经有的式子加括号,A使式子变大B使式子变小,问谁胜
因为只有+-*三个符号,所以问题不是很大,单纯DFS计算就行了,就是代码量略长,含符号的数据记录问题略多,写的很伤心
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
using namespace std;
#define INF 1000000007
int rval[11], n;
char ss[12][5];
int rop[11];
typedef pair<int, int> P;
int getval(int x, int y, char c)
{
if(c == '+')
{
return x + y;
}
if(c == '*')
{
return x * y;
}
return x - y;
}
P get(int val[], int op[], int deep, int flag)
{
P ans;
if(deep == 0)
{
ans.first = val[0];
ans.second = -1;
return ans;
}
if(flag)
{
ans.first = -INF;
}
else
{
ans.first = INF;
}
for(int i = 0; i < deep; i++)
{
int x = getval(val[i], val[i + 1], ss[op[i]][0]);
int cnt = 0;
int tmpop[11], tmpval[11];
for(int j = 0; j <= deep; j++)
{
if(j == i)
{
continue;
}
if(j == i + 1)
{
tmpval[cnt++] = x;
}
else
{
tmpval[cnt++] = val[j];
}
}
cnt = 0;
for(int j = 0; j < deep; j++)
{
if(j == i)
{
continue;
}
else
{
tmpop[cnt++] = op[j];
}
}
P tmp = get(tmpval, tmpop, deep - 1, !flag);
if(flag)
{
if(tmp.first > ans.first)
{
ans.first = tmp.first;
ans.second = i;
}
}
else
{
if(tmp.first < ans.first)
{
ans.first = tmp.first;
ans.second = i;
}
}
}
return ans;
}
int main()
{
int T, counter = 0;
scanf("%d", &T);
while(T--)
{
counter++;
scanf("%d", &n);
for(int i = 0; i < n; i++) scanf("%d%s", &rval[i], ss[i]);
for(int i = 0; i < n; i++) rop[i] = i;
scanf("%d", &rval[n]);
P ansx = get(rval, rop, n, 1);
P ansy = get(rval, rop, n, 0);
printf("Case %d:\n", counter);
printf("Player 1 (%d%s%d) leads to %d\n", rval[ansx.second], ss[ansx.second], rval[ansx.second + 1], ansx.first);
printf("Player 2 (%d%s%d) leads to %d\n", rval[ansy.second], ss[ansy.second], rval[ansy.second + 1], ansy.first);
if(ansx.first > -ansy.first)
{
printf("Player 1 wins\n");
}
else if(ansx.first < -ansy.first)
{
printf("Player 2 wins\n");
}
else
{
printf("Tie\n");
}
}
return 0;
}
G:Show Me the Money
当时看到这题目的时候第一反应是这竟然是星际1的加钱秘籍!(想太多了)
这题是要求一个最相近汇率,换个想法也就是求最短路,既然是最短路果断floyd上,注意一下数据全是整数就行了
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <cmath>
#include <map>
using namespace std;
map<string,int>q;
string ss[11];
long long a[33][33];
int ans,m;
string p1,p2,p;
void f()
{
int i,j,k,id,num,l;
long long sum=-1,in,aa,bb;
char h[22];
for(i=1; i<=ans; ++i)
{
for(j=1; j<=ans; ++j)
{
if(i!=j)
{
for(k=1; k<=ans; ++k)
{
if(i!=k&&j!=k)
{
if(a[j][i]==0||a[i][j]==0)
{
continue;
}
if(a[j][k]!=0)
{
continue;
}
a[j][k]=a[j][i]*a[i][k];
a[k][j]=a[k][i]*a[i][j];
}
}
}
}
}
id=q[p];
for(i=1; i<=ans; ++i)
{
if(i!=id&&a[i][id]!=0)
{
in=(long long)m*a[i][id]/a[id][i];
if(in*a[id][i]<(long long)m*a[i][id])
{
in++;
}
if(in<=100000)
{
if(sum==-1||in*a[id][i]*bb<sum*aa*a[i][id])
{
sum=in;
num=i;
aa=a[id][i];
bb=a[i][id];
}
}
}
}
l=ss[num].size();
for(i=0; i<l; ++i)
{
h[i]=ss[num][i];
}
h[l]=0;
printf("%lld %s\n",sum,h);
}
int main()
{
int t,i,cas=0,x,y;
char s[11],s1[11],s2[11];
while(scanf("%d",&t))
{
if(t==0)
{
break;
}
cas++;
q.clear();
ans=0;
memset(a,0,sizeof(a));
while(t--)
{
scanf("%d%s%s%d%s",&x,s1,s,&y,s2);
p1.assign(s1);
p2.assign(s2);
if(q[p1]==0)
{
q[p1]=++ans;
}
ss[q[p1]]=p1;
if(q[p2]==0)
{
q[p2]=++ans;
}
ss[q[p2]]=p2;
a[q[p1]][q[p2]]=x;
a[q[p2]][q[p1]]=y;
}
scanf("%d%s",&m,s);
printf("Case %d: ",cas);
p.assign(s);
f();
}
return 0;
}