Warmup for 2011 Asia Regional Chengdu

1004 Discount

被题意给坑了,总往打折那联想。后来发现前面的和题意无关。

给出n个数, 问从1开始不存在一个在这个n个数中取某几个数的和的最小值是多少。

可以先在n个数前补一个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\n",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\n",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 \n", i, edge[j].v);
		    }
		}*/
		for (int i=0 ; i<n ; ++i)
		{
		    //printf("deg==%d\n", deg[i]);
			if(!deg[i])addedge(n, i, 0);
		}

		dfs(n);
		int ans=0;
		for (int i=0 ; i<n ; ++i)
		{
		    //printf("dis==%d\n", dis[i]);
			ans=max(ans, dis[i]);
		}
		printf("%d\n",ans+1);
	}
	return 0;
}


 

你可能感兴趣的:(c,IM,联想)