跟金保学DP系列の一

来源:互联网 发布:爱知大学怎么样 编辑:程序博客网 时间:2024/06/11 15:25

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[n]);    }    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[n][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;}


0 0
原创粉丝点击