<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Hamko&#039;s Blog &#187; ProCon</title>
	<atom:link href="https://home.wakatabe.com/ryo/blog/?feed=rss2&#038;tag=procon" rel="self" type="application/rss+xml" />
	<link>https://home.wakatabe.com/ryo/blog</link>
	<description>This is an Intellect Hamster.</description>
	<lastBuildDate>Wed, 16 Apr 2014 07:45:37 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.2</generator>
		<item>
		<title>AOJ 0042: A Thief</title>
		<link>https://home.wakatabe.com/ryo/blog/?p=74</link>
		<comments>https://home.wakatabe.com/ryo/blog/?p=74#comments</comments>
		<pubDate>Thu, 27 Jun 2013 19:05:27 +0000</pubDate>
		<dc:creator>Hamko</dc:creator>
				<category><![CDATA[ProCon]]></category>

		<guid isPermaLink="false">http://home.wakatabe.com/ryo/blog/?p=74</guid>
		<description><![CDATA[A Thief コード ただのナップサック問題。だったので、紙を使わずに暗算で漸化式を立てて解きました。 dp[j][i] = i個目までの美術品をjの重さで盗んだ時の価値の最大値 初期状態は、dp[j][0] = 0 for all j 漸化式は、dp[j][i] = max(dp[j][i], dp[j-w][i]))で更新。]]></description>
			<content:encoded><![CDATA[<p><a href="http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0042">A Thief</a><br />
<a href="http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=703165">コード</a></p>
<p>ただのナップサック問題。だったので、紙を使わずに暗算で漸化式を立てて解きました。</p>
<p>dp[j][i] = i個目までの美術品をjの重さで盗んだ時の価値の最大値<br />
初期状態は、dp[j][0] = 0 for all j<br />
漸化式は、dp[j][i] = max(dp[j][i], dp[j-w][i]))で更新。</p>
<pre class="brush: cpp; title: ; notranslate">
#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;stdio.h&gt;
 
using namespace std;
 
#define WMAX 1000
#define NMAX 1000
int main(void)
{
    int W, n;
    int cyc = 0;
    while (cin &gt;&gt; W &amp;&amp; W &amp;&amp; cin &gt;&gt; n) {
        cyc++;
        int dp[WMAX+1][NMAX+1] = {};
        for (int i = 0; i &lt; n; i++) {
            int v, w;
            scanf(&quot;%d,%d&quot;, &amp;v, &amp;w);
            for (int j = 0; j &lt; W+1; j++) 
                dp[j][i+1] = max(dp[j][i], (j-w &gt;= 0 ? dp[j-w][i] + v : 0));
        }
        cout &lt;&lt; &quot;Case &quot; &lt;&lt; cyc &lt;&lt; &quot;:&quot; &lt;&lt; endl;
        for (int j = 0; j &lt; W+1; j++) {
            if (dp[j][n] == dp[W][n]) {
                cout &lt;&lt; dp[j][n] &lt;&lt; endl &lt;&lt; j &lt;&lt; endl;
                break;
            }
        }
    }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>https://home.wakatabe.com/ryo/blog/?feed=rss2&#038;p=74</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AOJ 2301: Sleeping Time</title>
		<link>https://home.wakatabe.com/ryo/blog/?p=68</link>
		<comments>https://home.wakatabe.com/ryo/blog/?p=68#comments</comments>
		<pubDate>Wed, 26 Jun 2013 23:59:20 +0000</pubDate>
		<dc:creator>Hamko</dc:creator>
				<category><![CDATA[ProCon]]></category>

		<guid isPermaLink="false">http://home.wakatabe.com/ryo/blog/?p=68</guid>
		<description><![CDATA[Sleeping Time コード 難易度Blue 350 (非公式難易度表) 「k回の睡眠でR=r, L=lとした時のPP」を返す関数retを考えて、深さ優先探索を行う発想は自然。 だが、これだけでは2^30で計算が間に合わない。 なので、l, rとP, Eの関係に枝刈り条件を加える。 ret内のl-rを呼び出し回数に関して指数関数的に収束させていくので、この条件はかなり強い枝刈りが可能である。]]></description>
			<content:encoded><![CDATA[<p><a href="http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2301">Sleeping Time</a><br />
<a href="http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=698061">コード</a></p>
<p>難易度<font color="blue">Blue 350</font> (<a href="https://docs.google.com/spreadsheet/ccc?key=0Ank515IguQc4dGJDR3FYOGZGTXQ5VHhNa1JmMDB4U0E#gid=0">非公式難易度表</a>)</p>
<p>「k回の睡眠でR=r, L=lとした時のPP」を返す関数retを考えて、深さ優先探索を行う発想は自然。<br />
だが、これだけでは2^30で計算が間に合わない。</p>
<p>なので、l, rとP, Eの関係に枝刈り条件を加える。<br />
ret内のl-rを呼び出し回数に関して指数関数的に収束させていくので、この条件はかなり強い枝刈りが可能である。</p>
<pre class="brush: cpp; title: ; notranslate">
#include &lt;iostream&gt;
#include &lt;cstdio&gt;
using namespace std;
#define abs(a) ((a) &gt; 0 ? (a) : -(a))
 
double P, E, T;
double ret(double k, double r, double l)
{
    double h = (r + l) / 2;
    if (k == 0) 
        return (abs(h-T) &lt; E ? 1.0 : 0.0);
    if (l &lt; T - E)
        return 0.0;
    if (r &gt; T + E) 
        return 0.0;
    if (T - E &lt; r &amp;&amp; l &lt; T + E) 
        return 1.0;
    if ((r+l)/2 &gt;= T) 
        return P * ret(k-1, r, h) + (1.0 - P) * ret(k-1, h, l);
    else
        return P * ret(k-1, h, l) + (1.0 - P) * ret(k-1, r, h);
}
 
int main(void)
{
    double K, R, L;
    cin &gt;&gt; K &gt;&gt; R &gt;&gt; L &gt;&gt; P &gt;&gt; E &gt;&gt; T;
    P = 1 - P;
 
    printf(&quot;%.6f&quot;, ret(K, R, L));
    return 0;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>https://home.wakatabe.com/ryo/blog/?feed=rss2&#038;p=68</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AOJ 2015: Square Route</title>
		<link>https://home.wakatabe.com/ryo/blog/?p=61</link>
		<comments>https://home.wakatabe.com/ryo/blog/?p=61#comments</comments>
		<pubDate>Wed, 26 Jun 2013 11:25:56 +0000</pubDate>
		<dc:creator>Hamko</dc:creator>
				<category><![CDATA[ProCon]]></category>

		<guid isPermaLink="false">http://home.wakatabe.com/ryo/blog/?p=61</guid>
		<description><![CDATA[Square Route コード 縦横で生成しうる辺の長さをそれぞれ全て求める。 それをソートしてしゃくとり法によって同じ長さの辺をかけて足し算していく。 でも、mapを使ってベクトルの内積をすればいいだけでは…と後で気づいた。]]></description>
			<content:encoded><![CDATA[<p><a href="http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2015">Square Route</a><br />
<a href="http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=693328">コード</a></p>
<p>縦横で生成しうる辺の長さをそれぞれ全て求める。<br />
それをソートしてしゃくとり法によって同じ長さの辺をかけて足し算していく。<br />
でも、mapを使ってベクトルの内積をすればいいだけでは…と後で気づいた。</p>
<pre class="brush: cpp; title: ; notranslate">
#include &amp;lt;iostream&amp;gt;
#include &amp;lt;algorithm&amp;gt;
#include &amp;lt;vector&amp;gt;

using namespace std;
#define NUMMAX 1500
#define CMAX (NUMMAX * (NUMMAX + 1) / 2)

void makecvec(vector&amp;lt;int&amp;gt;&amp;amp; in, vector&amp;lt;int&amp;gt;&amp;amp; out) 
{
    for (int ni = 0; ni &amp;lt; (int)in.size(); ni++) {
        for (int pi = 0; pi &amp;lt; (int)in.size() - ni; pi++) {
            int sum = 0;
            for (int si = 0; si &amp;lt; ni + 1; si++)
                sum += in[pi + si];
            out.push_back(sum);
        }
    }
}

int main(void)
{
    int n, m;
    while (cin &amp;gt;&amp;gt; n &amp;gt;&amp;gt; m) {
        if (!n &amp;amp;&amp;amp; !m) break;
        vector&amp;lt;int&amp;gt; h(n), w(m);
        for (int i = 0; i &amp;lt; n; i++) cin &amp;gt;&amp;gt; h[i];
        for (int i = 0; i &amp;lt; m; i++) cin &amp;gt;&amp;gt; w[i];

        vector&amp;lt;int&amp;gt; hs, ws;
        hs.reserve(CMAX), ws.reserve(CMAX);
        makecvec(h, hs), makecvec(w, ws);
        sort(hs.begin(), hs.end()), sort(ws.begin(), ws.end());

        int result = 0;
        int hi = 0, wi = 0;
        while (hi != (int)hs.size() &amp;amp;&amp;amp; wi != (int)ws.size()) {
            if (hs[hi] == ws[wi]) {
                int hn = 0, wn = 0;
                while (hi != (int)hs.size() &amp;amp;&amp;amp; hs[hi] == hs[hi-hn]) 
                    hi++, hn++;
                while (wi != (int)ws.size() &amp;amp;&amp;amp; ws[wi] == ws[wi-wn]) 
                    wi++, wn++;
                result += wn * hn;
            } else if (hs[hi] &amp;lt; ws[wi]) 
                hi++;
            else 
                wi++;
        }
        cout &amp;lt;&amp;lt; result &amp;lt;&amp;lt; endl;
    }

    return 0;
}

</pre>
]]></content:encoded>
			<wfw:commentRss>https://home.wakatabe.com/ryo/blog/?feed=rss2&#038;p=61</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AOJ 0557: 1年生 (A First Grader)</title>
		<link>https://home.wakatabe.com/ryo/blog/?p=54</link>
		<comments>https://home.wakatabe.com/ryo/blog/?p=54#comments</comments>
		<pubDate>Wed, 26 Jun 2013 11:17:27 +0000</pubDate>
		<dc:creator>Hamko</dc:creator>
				<category><![CDATA[ProCon]]></category>

		<guid isPermaLink="false">http://home.wakatabe.com/ryo/blog/?p=54</guid>
		<description><![CDATA[1年生 (A First Grader) コード DP強化週間 num[j] = j項目の数字 a[i][j] = j個目までの数字を使ってAOJ君が計算可能な数式によって、iを作る時の場合の数 とすると、以下のような漸化式が立てられる。 a[j][i] = a[j + num[i]][i-1] (もしj + num[i] < 21なら) + a[j - num[i]][i-1] (もしj - num[i] >= 0) i番目までで作れる0から20の数字を記憶する。何を展開して漸化式を立てるか、という問題は、もともと少ない自由度をわざわざ大きくする、という点で発想的だよなー。]]></description>
			<content:encoded><![CDATA[<p><a href="http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0557">1年生 (A First Grader)</a><br />
<a href="http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=698471">コード</a></p>
<p><a href="http://d.hatena.ne.jp/kyuridenamida/20111009/1318091499">DP強化週間</a></p>
<p> num[j] = j項目の数字<br />
 a[i][j] = j個目までの数字を使ってAOJ君が計算可能な数式によって、iを作る時の場合の数</p>
<p>とすると、以下のような漸化式が立てられる。</p>
<p> a[j][i] = a[j + num[i]][i-1] (もしj + num[i] < 21なら) + a[j - num[i]][i-1] (もしj - num[i] >= 0)</p>
<p>i番目までで作れる0から20の数字を記憶する。何を展開して漸化式を立てるか、という問題は、もともと少ない自由度をわざわざ大きくする、という点で発想的だよなー。</p>
<pre class="brush: cpp; title: ; notranslate">
#include &lt;iostream&gt;
#include &lt;vector&gt;

using namespace std;

int main(void)
{
    int n;
    cin &gt;&gt; n;
    int num[101];
    for (int i = 0; i &lt; n-1; i++) 
        cin &gt;&gt; num[i];
    int dest;
    cin &gt;&gt; dest;

    long long a[21][101] = {};
    a[num[0]][0] = 1;
    for (int i = 1; i &lt; n-1; i++) 
        for (int j = 0; j &lt; 21; j++) 
            a[j][i] += ((j + num[i] &lt; 21) ? a[j + num[i]][i-1] : 0) + ((j - num[i] &gt;= 0) ? a[j - num[i]][i-1] : 0);
    cout &lt;&lt; a[dest][n-1-1] &lt;&lt; endl;

    return 0;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>https://home.wakatabe.com/ryo/blog/?feed=rss2&#038;p=54</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AOJ 0168: Kannondou</title>
		<link>https://home.wakatabe.com/ryo/blog/?p=47</link>
		<comments>https://home.wakatabe.com/ryo/blog/?p=47#comments</comments>
		<pubDate>Wed, 26 Jun 2013 03:34:08 +0000</pubDate>
		<dc:creator>Hamko</dc:creator>
				<category><![CDATA[ProCon]]></category>

		<guid isPermaLink="false">http://home.wakatabe.com/ryo/blog/?p=47</guid>
		<description><![CDATA[Kannondou コード DP強化週間 「漸化式を立てる」という発想があるだけで勝ち。 1, 2, 3段までは初期値として手で数え、それ以降は-1, -2, -3段の場合の数の足しあわせとして漸化的に計算する。 ちなみに初期の3段目を間違えて3通りだと思って、サンプルが通らなかったので、なるべく自動に任せた方が良いなと教訓を得ました。 1, 2, 3段の数え間違いを避けたいなら、負の段の場合の数を0, 0段目を1, 1段目を0として、番兵法とかを使うと良いかもしれない。]]></description>
			<content:encoded><![CDATA[<p><a href="http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0168">Kannondou</a><br />
<a href="http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=698391">コード</a></p>
<p><a href="http://d.hatena.ne.jp/kyuridenamida/20111009/1318091499">DP強化週間</a></p>
<p>「漸化式を立てる」という発想があるだけで勝ち。<br />
1, 2, 3段までは初期値として手で数え、それ以降は-1, -2, -3段の場合の数の足しあわせとして漸化的に計算する。</p>
<p>ちなみに初期の3段目を間違えて3通りだと思って、サンプルが通らなかったので、なるべく自動に任せた方が良いなと教訓を得ました。</p>
<pre class="brush: cpp; title: ; notranslate">
#include &lt;iostream&gt;
using namespace std;
 
int main(void)
{
    int n;
    long long a[30] = {1, 2, 4};
    for (int i = 3; i &lt; 30; i++) 
        a[i] = a[i - 1] + a[i - 2] + a[i - 3];
    while (cin &gt;&gt; n &amp;&amp; n) 
        cout &lt;&lt; 1 + a[n-1] / 3650 &lt;&lt; endl;
 
    return 0;
}
</pre>
<p>1, 2, 3段の数え間違いを避けたいなら、負の段の場合の数を0, 0段目を1, 1段目を0として、番兵法とかを使うと良いかもしれない。</p>
]]></content:encoded>
			<wfw:commentRss>https://home.wakatabe.com/ryo/blog/?feed=rss2&#038;p=47</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
