您的位置:首页 > 其它

codeforces round 234 DIV2

2014-03-06 02:08 239 查看
     p1:Inna and Choose Options 

     模拟,12张牌,每张牌上是X或O,现在可以按每行1,2,3,4,6,12张的方式摆放,若某种摆放方式使得其中任意一列全部是X这就是一种合理的方式,求所有合理的摆放方式。直接模拟...

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
int n,m;
char s[20];
vector<int> ans;
char ss[20][20];
int main()
{
// freopen("in.txt","r",stdin);
int tt;
scanf("%d",&tt);

while(tt--)
{
ans.clear();
scanf("%s",s);
for (int i=1; i<=12; i++)
if (12 % i==0)
{
int j=12/i;
bool ok=true;
for (int ii=0; ii<i; ii++)
{
for (int jj=0; jj<j; jj++)
ss[ii][jj]=s[ii*j+jj];
}

// for (int ii=0; ii<i; ii++)
// {
// for (int jj=0; jj<j; jj++)
// cout<<ss[ii][jj];
// cout<<endl;
// }

for (int ii=0; ii<j; ii++)
{
ok=true;
for (int jj=0; jj<i; jj++)
if (ss[jj][ii]=='O') ok=false;
if (ok) break;
}
if (ok) ans.push_back(i);
}
cout<<ans.size();
for (int i=0; i<ans.size(); i++)
cout<<" "<<ans[i]<<"x"<<12/ans[i];
cout<<endl;
}
return 0;
}

   p2:Inna and New Matrix of Candies 
   N*M的矩阵,每行有唯一一个G和唯一一个S,每次操作可以使所有的不在S位置上的G向右移动任意步,问最少多少次操作可以使所有的G到S,无法实现输出-1.坑爹题意,一开始表述还不对让我猜了两次题意才猜过去= =...

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
char s[1050][1050];
int n,m,p,q,k;
int d[1050],c[1050];
bool move[2020];
int sub[2020];
int main()
{
// freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
for (int i=0; i<n; i++)
scanf("%s",s[i]);
bool ok=true;
for (int i=0; i<n; i++)
{
for (int j=0; j<m; j++)
if (s[i][j]=='G') d[i]=j;
else if (s[i][j]=='S') c[i]=j;
sub[i]=c[i]-d[i];
if (sub[i]<0) ok=false;
move[sub[i]]=true;
}
if (!ok) puts("-1");
else
{
int ans=0;
int last=0;
for (int i=1; i<=m; i++)
if (move[i]) ans++,last=i;
printf("%d\n",ans);
}

return 0;
}

p3:Inna and Huge Candy Matrix 
 

   N*M的矩阵有P个糖果,给出糖果的坐标,X次右旋,Y次镜面翻转,Z次左旋,求操作后所有糖果的坐标。

论变量名相似的傻×性= =..pt写成了tp结果挂复测了=话说这tm也能过样例么。。。首先x%=4,y%2=,z%=4,然后根据x,y,z分别执行三种操作就行了。。直接模拟不解释...

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
struct node
{
int x,y;
}pt[105000],tp[105000];
int n,m,p,x,y,z,k,q;

void right()
{
for (int i=0; i<p; i++)
tp[i].x=pt[i].y,tp[i].y=n-pt[i].x+1;
for (int i=0; i<p; i++)
pt[i]=tp[i];
}
void left()
{
for (int i=0; i<p; i++)
tp[i].x=m-pt[i].y+1,tp[i].y=pt[i].x;
for (int i=0; i<p; i++)
pt[i]=tp[i];
}
void flip()
{
for (int i=0; i<p; i++)
tp[i].x=pt[i].x,tp[i].y=m-pt[i].y+1;

for (int i=0; i<p; i++)
pt[i]=tp[i];
}

int main()
{
// freopen("in.txt","r",stdin);
scanf("%d%d%d%d%d%d",&n,&m,&x,&y,&z,&p);
x%=4;
y%=2;
z%=4;
for (int i=0; i<p; i++)
{
scanf("%d%d",&pt[i].x,&pt[i].y);
}
while (x)
{
right();
swap(n,m);
x--;
}
while(y)
{
flip();
y--;
}
while(z)
{
left();
swap(n,m);
z--;
}
for (int i=0; i<p; i++)
{
printf("%d %d\n",pt[i].x,pt[i].y);
}
return 0;
}

p4:Dima and Bacteria 

   这题也是个坑爹题意,翻译过来大致就是N个节点分为C种,同种节点编号相邻,给出每种节点的节点数。给出M条边u,v,w表示节点u--v间的通路花费为w。现在,若任意一对同种节点直接不能以代价0直接或间接到达的话,就输出no。否则求出不同种类节点间互达的最短路,如果某两种节点直接无法互打对应位置为-1.

    先跑一遍并查集,读边的时候若权值为0,就合并两个节点,这样在判断是否输出no的时候只要判断一下同种节点在不在一个集合里就行。读边的时候同时用跨越不同种类的边构造一个种类之间边权的邻接矩阵,然后跑一遍佛洛依德就ok了..

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
struct node
{
int u,v,w,next;
}edge[202000],ed[202000];
int g[202000],gg[202000];
int en,ee;
int n,m,c,k,p,q;
int size[202000];
int fa[202000];
int cc[202000];

int find(int x)
{
if (fa[x]==x) return x;
else return fa[x]=find(fa[x]);
}

int d[600][600];

int main()
{
// freopen("in.txt","r",stdin);
scanf("%d%d%d",&n,&m,&c);
int tp=1;
for (int i=1; i<=c; i++)
{
scanf("%d",&k);
cc[i]=k;
for (int j=0; j<k; j++,tp++)
{
size[tp]=i;
}
}
int x,y,z;
en=ee=0;
for (int i=1; i<=n; i++)
{
fa[i]=i;
}

for (int i=1; i<=m; i++)
{
scanf("%d%d%d",&x,&y,&z);
edge[en].u=x;
edge[en].v=y;
edge[en].w=z;
en++;
if (z==0)
{
x=find(x);
y=find(y);
fa[y]=x;
}
}
bool ok=true;
int ff=0;
size[0]=-1;
for (int i=1; i<=n; i++)
{
if (size[i]!=size[i-1])
{
ff=find(i);
}
else
{
if (find(i)!=ff)
{
ok=false;
break;
}
}
}
if (!ok)
{
puts("No");
return 0;
}
puts("Yes");
tp=1;
for (int i=0; i<=c; i++)
for (int j=0; j<=c; j++)
d[i][j]=(1<<29);

for (int i=0; i<=c; i++)
d[i][i]=0;

for (int i=0; i<m; i++)
{
int u=edge[i].u;
int v=edge[i].v;
if (size[u]!=size[v])
{
d[size[u]][size[v]]=min(d[size[u]][size[v]],edge[i].w);
d[size[v]][size[u]]=d[size[u]][size[v]];
}

}

for (int k=1; k<=c; k++)
for (int i=1; i<=c; i++)
if (i!=k)
for (int j=1; j<=c; j++)
if (j!=i && j!=k)
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);

for (int i=1; i<=c; i++)
{
for (int j=1; j<=c; j++)
if (d[i][j]<(1<<29))
cout<<d[i][j]<<" ";
else cout<<"-1 ";
cout<<endl;
}

return 0;
}

p5:Inna and Binary Logic

据说又是同时维护多颗线段树的题=。。。明天起来再看.....
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: