Warmup for 2011 Asia Regional Chengdu
1004 Discount
問題に穴をあけられて、いつも割引に連想します.後で前の問題とは関係ないことに気づいた.
n個の数を与えて、1からこのn個の数の中である数の和の最小値がどれだけあるかを聞く.
まずn個の数の前に1つの0を補って並べ替え、その後その接頭辞とsumを求める、sum[i-1]+1がa[i]より小さいか否かを判断し、もし小さいならansがsum[i-1]+1である.
簡単な帰納証明:
iが1に等しい場合、sum[0]=0,a[1]!=1の場合、必ず1の場合は発生しません.
i>=2の場合、i-1が上記の判断に対して成立すると仮定すると、すなわち、1からsum[i-1]までが前i-1の数で表され、sum[i-1]+1>=a[i]の場合、すべての1からsum[i-1]+a[i](すなわちsum[i])が求めることができる(sum[i-1]からsum[i]までの間がa[i]に加算された前に現れる数であることを検証するだけでよい)
1005
簡単DP、状態が良いDP[i][j][1,0]は、現在処理されているiを起点とするjを終点とし、状態が1-ピーク0-谷の最も多いスペース数であることを示し、
境界条件はdp[0][i][0]=0である.すなわち,0を起点とするすべての状態がピーク谷のスペース数である.
1009 Instrction Arrangement
メモリ検索または最長パス
問題に穴をあけられて、いつも割引に連想します.後で前の問題とは関係ないことに気づいた.
n個の数を与えて、1からこのn個の数の中である数の和の最小値がどれだけあるかを聞く.
まずn個の数の前に1つの0を補って並べ替え、その後その接頭辞とsumを求める、sum[i-1]+1がa[i]より小さいか否かを判断し、もし小さいならansがsum[i-1]+1である.
簡単な帰納証明:
iが1に等しい場合、sum[0]=0,a[1]!=1の場合、必ず1の場合は発生しません.
i>=2の場合、i-1が上記の判断に対して成立すると仮定すると、すなわち、1からsum[i-1]までが前i-1の数で表され、sum[i-1]+1>=a[i]の場合、すべての1からsum[i-1]+a[i](すなわちsum[i])が求めることができる(sum[i-1]からsum[i]までの間がa[i]に加算された前に現れる数であることを検証するだけでよい)
#include <cstdio>
#include <cstring>
#include <algorithm>
#define min(a,b) a>b?b:a;
using namespace std;
const int maxn=1005;
int sum[maxn];
int a[maxn];
int main ()
{
int n;
while (~scanf("%d",&n))
{
a[0]=sum[0]=0;
for (int i=1 ; i<=n ; ++i)
{
scanf("%d",a+i);
sum[i]=sum[i-1]+a[i];
}
sort(a,a+n+1);
int ans=sum[n]+1;
for (int i=0 ; i<n ; ++i)
{
if(sum[i]+1<a[i+1])
ans=min(sum[i]+1,ans);
}
printf("%d
",ans);
}
return 0;
}
1005
簡単DP、状態が良いDP[i][j][1,0]は、現在処理されているiを起点とするjを終点とし、状態が1-ピーク0-谷の最も多いスペース数であることを示し、
境界条件はdp[0][i][0]=0である.すなわち,0を起点とするすべての状態がピーク谷のスペース数である.
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=105;
int num[maxn][maxn];// i ,j
int dp[maxn][maxn][2];// i ,j ,1-- ,0-- ;
int n;
char str[maxn];
void DP()
{
memset (dp, -1, sizeof(dp));
for (int i=0 ; i<n ; ++i)
{
for (int j=i ; j<n ; ++j)
{
if(i==0)
dp[i][j][0]=0;
//1
for (int k=0 ; k<i ; ++k)
{
if(num[i][j]>num[k][i-1])
{
dp[i][j][1]=max(dp[i][j][1], dp[k][i-1][0]+1);
}
//0
if(num[i][j]<num[k][i-1])
{
dp[i][j][0]=max(dp[i][j][0], dp[k][i-1][1]+1);
}
}
}
}
int ans=0;
for (int i=0 ; i<n ; ++i)
{
ans=max(ans, dp[i][n-1][1]);
ans=max(ans, dp[i][n-1][0]);
}
printf("%d
",ans);
}
int main ()
{
while (~scanf("%d%s",&n,str))
{
for (int i=0 ; i<n ; ++i)
{
num[i][i]=str[i]-'0';
for (int j=i+1 ; j<n ; ++j)
{
num[i][j]=num[i][j-1]*10+str[j]-'0';
}
}
DP();
}
return 0;
}
1009 Instrction Arrangement
メモリ検索または最長パス
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct Edge {
int v,next,w;
}edge[100000+123];
int head[1005],cnt;
int dis[1005];
int deg[1005];
void addedge(int u, int v, int w)
{
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt;
cnt++;
}
void init ()
{
cnt=0;
memset (head, -1 , sizeof(head));
memset (dis, -1, sizeof(dis));
memset (deg, 0, sizeof(deg));
}
void dfs (int f)
{
int p=head[f];
if(~dis[f])return;
int ans=0;
for ( ; ~p ; p=edge[p].next)
{
dfs(edge[p].v);
ans=max(dis[edge[p].v]+edge[p].w, ans);
}
dis[f]=ans;
}
int main ()
{
int n,m;
int a,b,c;
while (~scanf("%d%d", &n, &m))
{
init();
for (int i=0 ; i<m ; ++i)
{
scanf("%d%d%d", &a, &b, &c);
++deg[b];
addedge(a,b,c);
}
/*
for (int i=0 ; i<n ; ++i)
{
for (int j=head[i]; ~j ; j=edge[j].next)
{
printf("%d %d
", i, edge[j].v);
}
}*/
for (int i=0 ; i<n ; ++i)
{
//printf("deg==%d
", deg[i]);
if(!deg[i])addedge(n, i, 0);
}
dfs(n);
int ans=0;
for (int i=0 ; i<n ; ++i)
{
//printf("dis==%d
", dis[i]);
ans=max(ans, dis[i]);
}
printf("%d
",ans+1);
}
return 0;
}