rainyroad

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

题意:给定一个自然数N,要求把N拆成若干个正整数相加的形式,整数可重复。拆分的方案数mod取余。

思路:完全背包裸题,因为整数可重复,N相当于给定的体积。

f[0]=1;
for(int i=1;i<=n;i++)
  for(int j=i;j<=n;j++)
    f[j]=(f[j]+f[j-i])%mod;
  

题意:

从N个人当中选出M个人作为法官。每个人都有一个ai属性和一个bi属性。现在要要求选出来的这M个人的ai之和与bi之和的差值最小,并且在差值一样的情况下要求输出ai之和与bi之和最大的方案。

思路

这个还是从N个人当中选出M个物品的问题,但是现在容量限制有了,但是每个人的价值,体积却没有。由于要求sum(ai) 与sum(bi) 之和最大,所以我们以每个人ai与bi之和作为这个人的价值。以ai与bi之差作为这个人的体积。则 以dp[N][M][k]作为状态,表示的就是从N个人当中选出M个人,这M个人的sum(ai)与sum(bi)之差为k时的总价值。但是这道题问的是方案,所以还要记录每一个状态是由哪一个状态转移而来的。所以用一个和D[i][j][k]来记录,最后在递归返回调用。这里说一个编程技巧,如果下标有负数,就设置一个偏移量,负数用偏移量减去某个数来表示,这样就把负数问题解决了。

题意:

给你一个含有N个顶点N条边的规范多变形,每条边的权值是 * '或者 ' + '。' * '代表 这条边两端顶点值相乘,'  +  '代表这条边两端顶点相加。第一步任意删除一条边。之后的N-1步每一次删除一条边,同时这条边的两个顶点做边上符号的运算变换成一个新的顶点。直到最后只剩下一个顶点。   现在问你最后剩下的点最大值可能是多少。

思路:区间dp,dp的思路就不说了。说几个编程的技巧。1.因为这里相当于是从这个环中任意顺序把 N个点进行合并。可以把N个点排成一条链,然后再这个链的末尾再复制一个同样的链。这里不用真的去复制一个链再后面,只要运用求余符号就可以。比如我要求i点往后m个距离的点j的具体值。则(i+m)%N就可以得到这个点的值了。这种手法经常用在环形dp要求当中。

2.如果dp的状态,某一个维度的值是有限的,比如只有0,1两个取值,这个时候就 不要用for循环去枚举了,直接dp[][][0].dp[][][1],

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
char c[55];
int val[55],dp_max[55][55],dp_min[55][55];
int cal(char x,int a,int b)
{
    if(x=='t')
        return a+b;
    return a*b;
}

int main()
{
   int n,i,j,k,l,p1,p2,ans,MAX,MIN,sign;
   while(scanf("%d",&n)!=EOF)
   {
       //cin>>c[i]>>val[i];
       for(int i=0;i<n;i++)
          cin>>c[i]>>val[i];

       for(int i=0;i<n;i++)
            dp_max[i][i]=dp_min[i][i]=val[i];
       for(int len=1;len<n;len++)
       {
           for(int i=0;i<n;i++)
           {
               MAX=-inf,MIN=inf;
               j=(i+len)%n;
               for(int k=0;k<len;k++)
               {
                   p1=(i+k)%n;
                   p2=(i+k+1)%n;
                   MAX=max(MAX,cal(c[p2],dp_max[i][p1],dp_max[p2][j]));
                   MAX=max(MAX,cal(c[p2],dp_min[i][p1],dp_min[p2][j]));
                   MIN=min(MIN,cal(c[p2],dp_max[i][p1],dp_max[p2][j]));
                   MIN=min(MIN,cal(c[p2],dp_min[i][p1],dp_min[p2][j]));
               }
               dp_max[i][j]=MAX;
               dp_min[i][j]=MIN;
           }
       }

       ans=-inf;
       for(int i=0;i<n;i++){
        j=(i+n-1)%n;
        ans=max(ans,dp_max[i][j]);
       }

        cout<<ans<<"\n";
        for(int i=0;i<n;i++){
            j=(i+n-1)%n;
            if(dp_max[i][j]==ans)
             cout<<i+1<<" ";
        }
        cout<<"\n";
   }
   return 0;
}

 

posted on 2019-07-15 13:59  rainyroad  阅读(158)  评论(0编辑  收藏  举报