您的位置:首页 > 其它

跟金保学DP系列の一

2015-08-03 09:44 246 查看
A:Ingenuous Cubrency

分析:硬币兑换问题,直接背包

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
const int INF=0x3f3f3f3f;
typedef long long LL;
const int maxn=1e5+100;
int tot=0;
int v[110];
LL dp[11000];
void init()
{
    for(int i=1;i*i*i<=10000;i++)
        v[tot++]=i*i*i;
}
int main()
{
    init();
    int n;
    while(~scanf("%d",&n))
    {
        CLEAR(dp,0);
        dp[0]=1;
        for(int i=0;i<tot;i++)
            for(int j=v[i];j<=n;j++) dp[j]+=dp[j-v[i]];
        printf("%lld\n",dp
);
    }
    return 0;
}


B:Partial Teacher

分析:我们对于每一个位置要判断1:后面以它最大,2:前面它最小,复杂度O(n^2)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
const int INF=0x3f3f3f3f;
typedef long long LL;
const int maxn=1e5+100;
int dp[maxn];
char str[maxn];
int n;
void solve()
{
    for(int i=0;i<n-1;i++)
    {
        int l=1,r=1;
        int pos1=i-1,pos2=i;
        while(pos1>=0&&str[pos1]!='L')
        {
            if(str[pos1]=='R') r++;
            pos1--;
        }
        while(pos2<n-1&&str[pos2]!='R')
        {
            if(str[pos2]=='L') l++;
            pos2++;
        }
        dp[i]=max(l,r);
    }
    if(str[n-2]=='R') dp[n-1]=dp[n-2]+1;
    else if(str[n-2]=='L') dp[n-1]=1;
    else dp[n-1]=dp[n-2];
}
int main()
{
    while(~scanf("%d",&n))
    {
        scanf("%s",str);
        solve();
        for(int i=0;i<n;i++)
            printf(i==n-1?"%d\n":"%d ",dp[i]);
    }
    return 0;
}


C:Porcelain

分析:看到这道题我的内心是崩溃的,因为m太TM大了,但是事实证明我太年轻了

显然我们要预处理每行取k个的最大值,这个复杂度约为(O(N^3))

然后就是背包dp[i][j]:前i行选j个的最大价值,复杂度约(O(N^2*M))最大情况下达1e8

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
const int INF=0x3f3f3f3f;
typedef long long LL;
const int maxn=1e5+100;
int n,m;
int k,x,all,a[110],num[110];
int dp[110][110],mx[110];
int sum[110][110];
int d[110][10005];
int dfs(int l,int r,int s)
{
    if(l>r) return 0;
    if(dp[l][r]!=-1)
        return dp[l][r];
    int ans=INF;
    if(l<=r) ans=min(ans,dfs(l+1,r,s+1)+a[l]);
    if(l<=r) ans=min(ans,dfs(l,r-1,s+1)+a[r]);
    mx[s]=max(mx[s],all-ans);
    return dp[l][r]=ans;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        REPF(i,1,n)
        {
            CLEAR(dp,-1);
            CLEAR(mx,0);
            all=0;
            scanf("%d",&k);
            num[i]=k;
            REPF(j,1,k)
            {
              scanf("%d",&a[j]);
              all+=a[j];
            }
            dfs(1,k,0);
            mx[k]=all;
            REPF(j,1,k)
              sum[i][j]=mx[j];
        }
        CLEAR(d,0);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                for(int k=0;k<=num[i];k++)
                {
                    if(k>j) continue;
                    d[i][j]=max(d[i-1][j-k]+sum[i][k],d[i][j]);
                }
            }
        }
        printf("%d\n",d
[m]);
    }
    return 0;
}


D:Eternal Victory

分析:开始题意没读清楚,给你n个点,n-1条边,每个点还必须走到,问你最小代价

这道题就是和FZU月赛题目一样的,求个最长路,然后总价值*2-最大价值的路

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
const int INF=0x3f3f3f3f;
typedef long long LL;
const int maxn=1e5+100;
struct node{
    int to,w;
    int next;
}e[maxn<<2];
int tot,n;
LL all,sum;
int head[maxn],vis[maxn];
void addedge(int u,int v,int w)
{
    e[tot].to=v;e[tot].next=head[u];e[tot].w=w;
    head[u]=tot++;
}
void dfs(int u,LL s)
{
    sum=max(sum,s);
    vis[u]=1;
    for(int i=head[u];i!=-1;i=e[i].next)
    {
        int to=e[i].to;
        if(!vis[to])
           dfs(to,s+e[i].w);
    }
}
int main()
{
    int x,y,w;
    while(~scanf("%d",&n))
    {
        int tot=0;
        all=sum=0;
        CLEAR(head,-1);
        CLEAR(vis,0);
        REPF(i,1,n-1)
        {
            scanf("%d%d%d",&x,&y,&w);
            addedge(x,y,w);
            addedge(y,x,w);
            all+=w;
        }
        dfs(1,0);
        printf("%lld\n",all*2-sum);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: