5001 - Making Quadrilaterals

5001 - Making Quadrilaterals
Asia - Kuala Lumpur - 2010/2011
http://acmicpc-live-archive.uva.es/nuevoportal/data/problem.php?p=5001

問題概要

長さが整数の棒をn本もっているときに、
四角形が作れない持ち方でかつ、
最も長い辺の最小値を求めよ。

解法

DP?
四角形ができない条件として、

  • ある棒sについて、sの長さよりそれ以下の長さの棒3本の長さを足しあわせても、

sの長さより大きくならないこと。

  • 上記の条件が全ての棒について当てはまること。

である。
今n本の解を求めたい場合、

  • もし、n本の解でn-1本の解を含まない解の方が、n-1本の解より小さいものが存在すれば、その最大の辺を取り除いても四角形がつくれないはずであるので、n-1本の解についても最適なものが見つかってしまうので矛盾。

よって、n-1本の解に棒を足していくことで最適ケースが作れる。その棒の足し方は、

  • n-1本の解の最大の辺より小さな辺を追加できると仮定すると、n-1本の解がより良い解が見つかるということになり矛盾。
  • n-1本の解の最大の辺と同じ長さの辺を追加できると仮定すると、その追加した辺が
    • ある棒sについて、sの長さよりそれ以下の長さの棒3本の長さを足しあわせても、

sの長さより大きくならないこと。
という条件に当てはまらないので解に適さない。

  • n-1本の解の最大の辺より長い辺は、n-1本の解で作れる最大の3本の合計(つまり長い方から三本)以上の辺を加えられる。

よって、n-1本の解の長い方から3本を足しあわせたものがn本の解の最大の長さの辺である。

ソース

#include<iostream>
#include<cstdio>

#define REP(i,b,n) for(int i=b;i<(int)n;i++)

using namespace std;
typedef unsigned long long lli;
const int N = 61;

lli t[N][3];

void solve(){
  t[4][0] = 1;
  t[4][1] = 1;
  t[4][2] = 3;
  REP(i, 5, N){
    t[i][0] = t[i-1][1];
    t[i][1] = t[i-1][2];
    t[i][2] = t[i-1][0] + t[i-1][1] + t[i-1][2];
  }
}

int main(){
  solve();
  int n;
  int tc = 0;
  while(cin >> n){
    if( n == 0)break;
    tc++;
    printf("Case %d: %Ld\n",tc, t[n][2]); 
  }
  return 0;
}