2190Angel Stairs

http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2190
天使が音色を奏でながら階段を下りてくる問題。
動的計画法と幅優先探索の混合で最下位実行速度でアセプト。
なんか解けただけで満足してしまった問題。
動的計画法で、n個目の音を鳴らす時、n-1個目までの音を鳴らしおえた段以外はすべて無視するということで高速化を図ってます。



#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<map>
#include<vector>
std::map<std::string,int> toNo;
int mod=12;
void set(){
toNo["C"] =0;
toNo["C#"]=1;
toNo["D"] =2;
toNo["D#"]=3;
toNo["E"] =4;
toNo["F"] =5;
toNo["F#"]=6;
toNo["G"] =7;
toNo["G#"]=8;
toNo["A"] =9;
toNo["A#"]=10;
toNo["B"] =11;
}
int memo[2][50002];
int n,m;
void calc(){
std::string str;
std::vector<int> dan[12];
for(int i=0;i<n;i++){
	std::cin>>str;
	dan[toNo[str]].push_back(i+1);
}
int now,p,size,oto,nextTurn,nowTurn,up=1;
bool nextOK,allBad=false;
memset(memo,-1,sizeof(memo));
memo[0][0]=0;
for(int i=0;i<m;i++){
	std::cin>>str;
	if(allBad==true) continue;
	up+=2;
	nextTurn=(i+1)&1;
	nowTurn =i&1;
	nextOK=false;	
	//一段降りる
	now=toNo[str];
	oto=now;
	size=dan[oto].size();
	for(int j=0;j<size;j++){
		p=dan[oto][j];
		if(p>up) break;
		if(p-1>=0 && memo[nowTurn][p-1]==i){
			memo[nextTurn][p]=i+1;
			nextOK=true;
		}
	}
	//2段降りる
	oto=(now+11)%mod;
	size=dan[oto].size();
	for(int j=0;j<size;j++){
		p=dan[oto][j];
		if(p>up)break;
		if(p-2>=0 && memo[nowTurn][p-2]==i){
			memo[nextTurn][p]=i+1;
			nextOK=true;
		}
	}
	//一段上がる
	oto=(now+1)%mod;
	size=dan[oto].size();
	for(int j=0;j<size;j++){
		p=dan[oto][j];
		if(p>up) break;
		if(p+1<n+1 && memo[nowTurn][p+1]==i){
			memo[nextTurn][p]=i+1;
			nextOK=true;
		}
	}
	if(nextOK==false){
		allBad=true;
	}
	//for(int j=1;j<=n;j++)printf("%d ",memo[nextTurn][j]);
	//printf("\n");
}
printf("%s\n",memo[nextTurn][n]>=m||memo[nextTurn][n-1]>=m?"Yes":"No");
}
int main(){
set();
int r;
scanf("%d",&r);
while(r--){
	scanf("%d %d",&n,&m);
	calc();
}
}

タグ:

+ タグ編集
  • タグ:

このサイトはreCAPTCHAによって保護されており、Googleの プライバシーポリシー利用規約 が適用されます。

最終更新:2012年03月15日 07:50