JOI2012本選2番

dp[ap=Aの何枚目か][bp=Bの何枚目か]でDPした。

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int dp[5010][5010];
int ac[5010],bc[5010];
int rec(int ap,int bp){
	if(ap<0||bp<0)
		return 0;
	else if(dp[ap][bp]!=-1)
		return dp[ap][bp];
	else{
		int r=rec(ap-1,bp);
		if(ac[ap]==bc[bp])
			r=max(r,rec(ap-1,bp-1)+1);
		return dp[ap][bp]=r;
	}
}
int main(){
	int an,bn;
	scanf("%d%d",&an,&bn);
	for(int i=0;i<an;i++)
		scanf("%d",ac+i);
	for(int i=0;i<bn;i++)
		scanf("%d",bc+i);
	memset(dp,-1,sizeof(dp));
	int ans=0;
	for(int i=0;i<an;i++)
		for(int j=0;j<bn;j++)
			ans=max(ans,rec(i,j));
	printf("%d\n",ans);
	return 0;
}

JOI2012本選1番

解説を聞いてから自分のやっていたことがRunLength圧縮と同じであると気づいた。

#include <stdio.h>
#include <vector>
using namespace std;
char in[10000000+10];
int main(){
	scanf("%s",in);
	vector<int> ch,sq;
	int c=in[0],s=1;
	for(int i=1;in[i]!=0&&in[i]!='\n';i++){
		if(c!=in[i]){
			ch.push_back(c);
			sq.push_back(s);
			c=in[i];
			s=1;
		}else{
			s++;
		}
	}
	ch.push_back(c);
	sq.push_back(s);
	int ans=0;
	for(int i=0;i+2<(int)ch.size();i++){
		if(ch[i]=='J'&&ch[i+1]=='O'&&ch[i+2]=='I'&&sq[i+1]<=min(sq[i],sq[i+2]))
			ans=max(ans,min(sq[i],sq[i+1]));
	}
	printf("%d\n",ans);
	return 0;
}

JOI2011本選5番

kについて二分探索した後、その判定を頑張ってO(n)で出来るようにする。

#include <stdio.h>
#include <utility>
#include <set>
#include <algorithm>
#include <vector>
#define MAX_V 1000100

using namespace std;

int n;
int ai[MAX_V],can[MAX_V],bi2ai[MAX_V];
pair<int,int> bi[MAX_V];

int ok(int k)
{
	if(k==0)
		return 1;
	double sumA=0;
	for(int i=0;i<n;i++)
		can[i]=1;
	for(int i=0;i<k;i++)
		sumA+=ai[i];
	int lastA=k-1;
	for(int b=0;b+k<=n;b++)
	{
		if(sumA/(double)k<=(double)bi[b].first)
			return 1;
		int tP=bi2ai[b];
		can[tP]=0;
		if(tP<=lastA)
		{
			sumA-=ai[tP];
			lastA++;
			if(lastA>=n)
				return 0;
			while(!can[lastA])
				lastA++;
			sumA+=ai[lastA];
		}
	}
	return 0;
}

int main()
{
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		ai[i]=a;
		can[i]=1;
		bi2ai[i]=-1;
		bi[i]=make_pair(b,-a);
	}
	sort(ai,ai+n);
	sort(bi,bi+n);
	for(int i=0;i<n;i++)
	{
		int a=-bi[i].second;
		int tB=lower_bound(ai,ai+n,a)-ai;
		int tE=upper_bound(ai,ai+n,a)-ai;
		int tP;
		for(tP=tB;tP<tE;tP++)
			if(can[tP])
				break;
		can[tP]=0;
		bi2ai[i]=tP;
	}
	int b=0,c=n;
	while(1<c-b)
	{
		int m=(b+c)/2;
		if(ok(m))
			b=m;
		else
			c=m;
	}
	if(ok(c))
		printf("%d\n",c);
	else
		printf("%d\n",b);
	return 0;
}

SuperCon2011に参加しました

2011年8月22日(月) 〜 26日(金)にかけて大阪大学豊中キャンパスで
SuperCon2011にチームMKとして参加してきました。
 
今回の課題は「https://www.cp.cmc.osaka-u.ac.jp/supercon/naklon.html」。
リンクをクリックして表示されるのはSIZE=8のものですが
実際の本選はSIZE=250という巨大なくろんなので全探索はできません。
 
それではどうするか。
僕達のチーム(主に僕)は2つの方針を考えました。
1:1000手ほど乱択しそれを何度か繰り替えして最もよいものを選ぶことを何度か繰り返す
2:5手ほど全探索して評価関数で評価して最も良い手を選ぶ。
 
1は相方に実装してもらったのですがあまり結果が芳しくなかったので
僕は2を頑張っていました。
 
3日目の昼頃に評価関数を得点÷落ちた玉に変えた所
非常に結果が良かったので最後までその方針で行きました
 
結果は5位でした。
2位から5位まではほとんど同じ方針だったということなので悔しいです

Haskellで数式をパースする

使い方
 :load で読み込んだ後
 myEquation "1+2*3"

import Text.ParserCombinators.Parsec

myDigit :: Parser Char
myDigit = oneOf ['0'..'9']

myNumberString :: Parser String
myNumberString = do
	c<-myDigit
	do
			cs <- myNumberString
			return (c:cs)
		<|> return [c]

myNumber :: Parser Integer
myNumber = do
	s<-myNumberString
	return (read s)

myPlusMinus :: Parser Char
myPlusMinus = oneOf "+-"

myMultiDiv :: Parser Char
myMultiDiv = oneOf "*/"

myCalc '+' left right = (left+right)
myCalc '-' left right = (left-right)
myCalc '*' left right = (left*right)
myCalc '/' _ 0 = 0
myCalc '/' left right = (left `div` right)

myEquation :: Parser Integer
myEquation = do{ left<-myFactor; rest left }
		where
			rest l = do{ op<-myPlusMinus
					;r<-myFactor
					;rest (myCalc op l r)
					}
				<|> return l
{-<|> do{ op<-myPlusMinus
		;right<-myEquation
		;return (myCalc op x right
		}-}

myFactor :: Parser Integer
--myFactor = do{ x<-myTerm; rest x}
myFactor = do {left<-myTerm; rest left }
		where
			rest l = do{ op<-myMultiDiv
					;r<-myTerm
					;rest (myCalc op l r)
					}
				<|> return l
				{-
		left<-myFactor
		op<-myMultiDiv
		right<-myTerm
		return (myCalc op left right)
	<|>	myTerm-}

myTerm :: Parser Integer
myTerm = do
		char '('
		x<-myEquation
		char ')'
		return x
	<|> myNumber

{-

myExpr2List String->[String]
myExpr2List "" = ""
myExpr2List x:xs = if myPlusMinus 

myFactor :: Parser Integer
myFactor =
	do
		char '('
		x<-myExpr
		char ')'
		return x
	<|>	myExpr

myExpr :: Parser Integer
myExpr = do
		left<-myNumber
		do
				op<-myPlusMinus
				right<-myFactor
				return (myCalc op left right)
			<|> return left
	<|> myFactor
-}

HaskellでHTMLをパースする

使い方
 hoge.hsに下のコードを保存する。
 runghc "hoge.hs" "target.html" ※ダブルクオーテーションは必要

 このままでは空行が大量に含まれているので
 runghc "hoge.hs" "target.html" | sed '/^ *$/d'
 すると良い

--sed '/^ *$/d'
import Text.ParserCombinators.Parsec
import System.Environment

data MyTag = MakeMyTag {tagName::String,tagContent::[String]} deriving (Eq,Show)

testMyTag = MakeMyTag "aa" ["bb","cc"]

data MyHTMLContent = MakeContentChild { myLeftTag::MyTag,myContentMain::[MyHTMLContent],myRightTag::MyTag }
	| MakeTagSelf MyTag
	| MakePlainText { myText::String }
	| MakeComment
	deriving (Eq,Show)

testHTMLContent1 = (MakePlainText "dd")
testHTMLContent2 = (MakeTagSelf testMyTag)
testHTMLContent3 = (MakeContentChild testMyTag [testHTMLContent1,testHTMLContent2] testMyTag)

outputHTML (MakeComment) n = ""
outputHTML (MakePlainText "") n = ""
outputHTML (MakePlainText s) n = (sTab n++s++"\n")
outputHTML (MakeTagSelf x) n = ""
outputHTML (MakeContentChild l con r) n = sCon con (n+1)
		
sTab 0 = ""
sTab n = "  "++sTab (n-1)

sCon [] _ = "" 
sCon (x:xs) n = (outputHTML x n++sCon xs n)

main = do
	inStr<-getArgs
	tmp <- parseFromFile myHTML (head inStr)
	case tmp of
		Left err -> do {print "error"; }
		Right xs -> do {putStrLn (func xs); }

func :: [MyHTMLContent]->String
func [] = ""
func (x:xs) = (outputHTML x 0)++(func xs)

isNotEqual c = if c=='='
	then False
	else True

myDigit :: Parser Char
myDigit = oneOf ['0'..'9']

myNumberString :: Parser String
myNumberString = do
	c<-myDigit
	do
			cs <- myNumberString
			return (c:cs)
		<|> return [c]

myTagContentLeft :: Parser String
myTagContentLeft = many1 (noneOf "=>/")
-- myTagContentLeft = many1 (satisfy (\c -> c /= '='))
--myTagContentLeft = many1 (alphaNum <|> char ':')
{-where
		rest = do{ x<-satisfy (\c -> c /= '=')
				; xs<-rest
				; return (x:xs) 
				}
			<|> return ""
-}

myTagContentRight :: Parser String
myTagContentRight = do
		lD<-char '"'
		mD<-inC
		rD<-char '"'
		return ([lD]++mD++[rD])
	<|> myNumberString
		where

			inC = do{ x<-satisfy (\c -> c /= '"')
					; xs<-inC
					; return (x:xs)
					}
				<|> return ""

myTagContent :: Parser String
myTagContent = do
	left<-myTagContentLeft
	char '='
	right<-myTagContentRight
	return (left++"="++right)

myTagName :: Parser String
myTagName = many1 alphaNum

myEndTag :: Parser MyTag
myEndTag = do
	string "</"
	many space
	name<-myTagName
	many space
	char '>'
	return (MakeMyTag name [])

myBeginTag :: Parser MyTag
myBeginTag = do
	char '<'
	name<-myTagName
	many space
	tagContent<-many p
	char '>'
	return (MakeMyTag name tagContent)
		where
			p = do
				r<-myTagContent
				many space
				return r

mySelfTag :: Parser MyTag
mySelfTag = do
	char '<'
	name<-myTagName
	many space
	tagContent<-many p
	string "/>"
	return (MakeMyTag name tagContent)
		where
			p = do
				r<-myTagContent
				many space
				return r

myComment :: Parser MyHTMLContent
myComment = do
		string "<!--"
		rest "aa"
		char '>'
		return MakeComment
	-- <?> "myComment"
	
	where 
		rest before =
			if before == "--"
			then return ()
			else do
				x<-anyChar
				rest (tail before++[x])
				
myContent :: Parser MyHTMLContent
myContent = do {p<-many1 (satisfy (\c-> c/='<')); return ( MakePlainText p)}
	<|> myBeginAndEndTag
		<|> do  {t<-try mySelfTag; return (MakeTagSelf t)}
		<|> try myComment
		<?> "myContent"

{--myContent = try( do {b<-myBeginTag; l<-myContentList; e<-myEndTag; return  (MakeContentChild b l e)})
		<|> try( do  {t<-mySelfTag; return (MakeTagSelf t)})
		<|>  do {p<-many1 (satisfy (\c-> c/='<')); return ( MakePlainText p)}--}

myBeginAndEndTag :: Parser MyHTMLContent
myBeginAndEndTag = do
	b<-try myBeginTag
	l<-myContentList
	e<-myEndTag
	if tagName b == tagName e 
		then return (MakeContentChild b l e)
		else fail $ "tag don't match "++tagName b++" and "++tagName e
	
myContentList :: Parser [MyHTMLContent]
myContentList = (do	{ r<-myContent; l<-myContentList; return ([r]++l)})
			<|> do return []
--myContentList = try (do	{r<-myContent; many myComment; l<-myContentList; return ([r]++l)})

myHTML :: Parser [MyHTMLContent]
myHTML = do
	x <- myContentList
	eof
	return x