読者です 読者をやめる 読者になる 読者になる

JAG 春コンテスト

wakabaです。1位でした。

自分が解いた問題だけいろいろ書いておきます。

B: Cube Coloring
気合で数えるだけ。必要な気合も少なめ。
(687Byte)

#include<stdio.h>
#include<algorithm>
using namespace std;
long long p[1100];
long long q[1100];
long long r[1100];
int ABS(int a){
	return max(a,-a);
}
int main(){
	int a,b,c,d,e,f,g;
	scanf("%d%d%d%d%d%d%d",&a,&b,&c,&d,&e,&f,&g);
	for(int i=0;i<a;i++)p[ABS(i-d)%g]++;
	for(int i=0;i<g;i++){
		int s=(e+1+g-i-1)/g;
		int t=(b-e+g-i-1)/g;
		for(int j=0;j<g;j++)q[(i+j)%g]+=p[j]*(s+t);
	}
	for(int i=0;i<g;i++)q[i]-=p[i];
	for(int i=0;i<g;i++){
		int s=(f+1+g-i-1)/g;
		int t=(c-f+g-i-1)/g;
		for(int j=0;j<g;j++)r[(i+j)%g]+=q[j]*(s+t);
	}
	for(int i=0;i<g;i++)r[i]-=q[i];
	for(int i=0;i<g;i++){
		if(i)printf(" ");
		printf("%lld",r[i]);
	}
	printf("\n");
}

E: Parentheses
上昇、下降に分けてそれぞれ前と後ろからgreedy。そもそも個数が違ったらNo,を忘れていた…
(1261Byte)

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char str[1000];
int v[1000];
int L[1000];
int R[1000];
bool used[1000];
int main(){
	int a;
	scanf("%d",&a);
	for(int i=0;i<a;i++){
		scanf("%s",str);
		int n=strlen(str);
		int now=0;
		for(int j=0;j<n;j++){
			if(str[j]=='(')now++;
			else now--;
			L[i]=min(L[i],now);
		}
		v[i]=now;
		now=0;
		for(int j=n-1;j>=0;j--){
			if(str[j]==')')now++;
			else now--;
			R[i]=min(R[i],now);
		}
	}
	int sum=0;
	for(int i=0;i<a;i++)sum+=v[i];
	if(sum!=0){
		printf("No\n");
		return 0;
	}
	int val=0;
	for(int i=0;i<a;i++){
		int use=-1;
		int m=0;
		for(int j=0;j<a;j++){
			if(!used[j]&&v[j]>0&&val+L[j]>=0){
				if(m<v[j]){
					m=v[j];
					use=j;
				}
			}
		}
		if(~use){
			used[use]=true;
			val+=m;
		}
	}
	for(int i=0;i<a;i++){
		if(v[i]==0&&val+L[i]>=0)used[i]=true;
	}
	val=0;
	for(int i=0;i<a;i++){
		int use=-1;
		int m=0;
		for(int j=0;j<a;j++){
			if(!used[j]&&v[j]<0&&val+R[j]>=0){
				if(m<-v[j]){
					m=-v[j];
					use=j;
				}
			}
		}
		if(~use){
			used[use]=true;
			val+=m;
		}
	}
	bool ok=true;
	for(int i=0;i<a;i++)if(!used[i])ok=false;
	if(ok)printf("Yes\n");
	else printf("No\n");
}

C: Decoding Ancient Messages
でかい数で最小費用流。なるほどなあ。あとは実装をがんばる。
(2932Byte)

#include<bits/stdc++.h>
using namespace std;
typedef int wint;
struct cint{
	int num[55];
	cint(){for(int i=0;i<55;i++)num[i]=0;}
	cint operator+(const cint &a){
		cint ret;
		for(int i=0;i<55;i++)ret.num[i]=num[i]+a.num[i];
		return ret;
	}
	cint operator-(const cint &a){
		cint ret;
		for(int i=0;i<55;i++)ret.num[i]=num[i]-a.num[i];
		return ret;
	}
	cint operator-(){
		cint ret;
		for(int i=0;i<55;i++)ret.num[i]=-num[i];
		return ret;
	}
	cint operator*(const int &k){
		cint ret;
		for(int i=0;i<55;i++)ret.num[i]=num[i]*k;
		return ret;
	}
};
inline bool operator<(const cint &a,const cint &b){
	for(int i=0;i<55;i++){
		if(a.num[i]!=b.num[i])return a.num[i]<b.num[i];
	}
	return false;
}
namespace MCF{
	//お前さっき俺達がコード書いてる時、チラチラライブラリみてただろ。
}
char str[100][100];
int main(){
	int a;
	scanf("%d",&a);
	for(int i=0;i<a;i++)scanf("%s",str[i]);
	MCF::init(a*2+2);
	int s=a*2;
	int t=a*2+1;
	for(int i=0;i<a;i++){
		MCF::ae(s,i,1,cint());
		MCF::ae(a+i,t,1,cint());
	}
	for(int i=0;i<a;i++){
		for(int j=0;j<a;j++){
			cint val;
			if('A'<=str[i][j]&&str[i][j]<='Z')val.num[str[i][j]-'A']--;
			else val.num[str[i][j]-'a'+26]--;
			MCF::ae(i,a+j,1,val);
		}
	}
	MCF::solve(s,t,a);
	for(int i=0;i<52;i++){
		for(int j=0;j<-(MCF::toc.num[i]);j++){
			if(i<26)printf("%c",'A'+i);
			else printf("%c",'a'+i-26);
		}
	}
	printf("\n");
}

F: Polygon Guards
まず幾何をする。答えはどうせ10頂点以下だろうから適当に探索すれば間に合いそう*1。ひたすら実装する。
(3272Byte)

#include<bits/stdc++.h>
using namespace std;
//あ、お前さ木村さ、さっき俺達がコッ、コード出した時さ、なかなかAC来なかったよな?
//そうだよ
//見たけりゃライブラリ見せてやるよ、ほら、見ろよ見ろよ
int g[100][100];
long long to[100];
Pt poly[100];
int wolf;
int N;
int dfs(int a,int b,long long c){
	if(a==N){
		if(c==(1LL<<N)-1)return 1;
		return 0;
	}
	int val=dfs(a+1,b,c);
	if(val)return 1;
	
	if(b==wolf)return 0;
	
	val=dfs(a+1,b+1,c|to[a]);
	
	if(val)return 1;
	return 0;
}
int X[100];
int Y[100];
pair<double,Pt> pts[1000];
int main(){
	int a;
	scanf("%d",&a);
	N=a;
	for(int i=0;i<a;i++)scanf("%d%d",X+i,Y+i);
	for(int i=0;i<a;i++)g[i][i]=1;
	for(int i=0;i<a;i++)poly[i]=Pt(X[i],Y[i]);
	for(int i=0;i<a;i++)
		for(int j=0;j<a;j++){
			if(i==j)continue;
			int sz=0;
			
			//printf("%d %d:\n",i,j);
			for(int k=0;k<a;k++){
				if(iLL(poly[i],poly[j],poly[k],poly[(k+1)%a])!=-1&&iSS(poly[i],poly[j],poly[k],poly[(k+1)%a])){
					Pt point=pLL(poly[i],poly[j],poly[k],poly[(k+1)%a]);
					pts[sz++]=make_pair(point.x*114514+point.y,point);
				}
			}
			if(sz<2){
				g[i][j]=1;
				continue;
			}
			std::sort(pts,pts+sz);
			bool ok=true;
			for(int k=0;k<sz-1;k++){
				Pt M=(pts[k].second+pts[k+1].second)/2.0;
				//printf("(%f, %f)",M.x,M.y);
				if(!~sGP(a,poly,M)){
					ok=false;
				//	printf("---!!!---");
				}
				//printf("\n");
			}
			if(ok)g[i][j]=1;
		}
	
	//for(int i=0;i<a;i++){
	//	for(int j=0;j<a;j++)printf("%d ",g[i][j]);
	//	printf("\n");
	//}
	for(int i=0;i<a;i++)
		for(int j=0;j<a;j++)
			if(g[i][j])to[i]+=(1LL<<j);
	for(int i=1;i<=9;i++){
		wolf=i;
		if(dfs(0,0,0)){
			printf("%d\n",i);
			return 0;
		}
	}
	printf("10\n");
}

以上です。

*1:実際は9頂点以下らしいです