0x52~0x54

0x52~0x54

Pick a few wrote.

a.[√] coins

Title transfer

sol:

This is a multi-template title backpack, but not conventional binary optimized. Monotone queue optimization is possible.

It should be a much simpler method.

Take note of this problem as long as interest exists, it is possible to consider setting \ (f [x] \) represents the x can be represented.

The coin then for i, if there is considered \ (F [XA [I]] =. 1 \) , then the \ (F [X] =. 1 \) .

However, since the number of coins is defined, it is possible to use a \ (CNT [x] \) to record the number of coins constituting x i only need.

They do not exceed the limit, you can continue the transfer.

code:

#include<cmath>
#include<string>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define RG register
#define IL inline
#define LL long long
#define DB double
using namespace std;

const int N=101;
const int M=1e5+1;

int n,m,ans,a[N],c[N],f[M],cnt[M];

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF&&n&&m) {
        RG int i,j;
        for(i=1;i<=n;++i) scanf("%d",&a[i]);
        for(i=1;i<=n;++i) scanf("%d",&c[i]);
        memset(f,0,sizeof(f));
        for(i=1,ans=0,f[0]=1;i<=n;++i) {
            memset(cnt,0,sizeof(cnt));
            for(j=a[i];j<=m;++j) {
                if(!f[j]&&f[j-a[i]]&&cnt[j-a[i]]<c[i]) 
                    f[j]=1,cnt[j]=cnt[j-a[i]]+1,++ans;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

b.[√]Polygon

Title transfer

sol:

Optionally, after one side is first cut off, it can be found a more obvious section DP.

Respectively, so that \ (f [l, r] , g [l, r] \) represents the maximum and minimum values from l to r after the merger.

The maximum value, since when the operator needs to pay attention to two small negative number when multiplied by multiplication may be larger, so that the transfer should be:
\ [F [I] [J] = {i≤k max_ < j} \ lbrace f [i] [k] + f [k + 1] [j] \ rbrace \\ f [i] [j] = max_ {i≤k <j} \ lbrace max (f [i] [ k] * f [k + 1 ] [j], g [i] [k] * g [k + 1] [j]) \ rbrace \ operable by \]
for the minimum value, since when the operator is Note that when the multiplication is multiplied by a positive and negative may be smaller, so that the transfer should be:
\ [G [I] [J] = {i≤k min_ <J} \ lbrace G [I] [K] + G [k + 1] [j] \ rbrace \\ g [i] [j] = min_ {i≤k <j} \ lbrace g [i] [k] * g [k + 1] [j], g [ i] [k] * f [ k + 1] [j], f [i] [k] * g [k + 1] [j] \ rbrace \ operable by \]
code:

#include<cmath>
#include<string>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define RG register
#define IL inline
#define int long long
#define DB double
using namespace std;

const int N=111;
const int inf=0x3f3f3f3f;

char inp[3];
int n,ans,a[N],op[N],f[N][N],g[N][N];

signed main()
{
    RG int i,j,k;
    scanf("%lld",&n);
    for(i=1;i<=n<<1;++i) {
        if(i&1) {
            scanf("%s",inp);
            if(inp[0]=='t') op[i+1>>1]=1;
            else op[i+1>>1]=2;
        }
        else scanf("%lld",&a[i>>1]);
    }
    for(i=1;i<=n;++i) a[n+i]=a[i],op[n+i]=op[i];
    memset(f,0xcf,sizeof(f));
    memset(g,0x3f,sizeof(g));
    for(i=1;i<=n<<1;++i) f[i][i]=g[i][i]=a[i];
    for(i=n<<1;i>=1;--i)
        for(j=i+1;j<=i+n-1&&j<=n<<1;++j) 
            for(k=i;k<j;++k) {
                if(op[k+1]==1) {
                    f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]);
                    g[i][j]=min(g[i][j],g[i][k]+g[k+1][j]);
                }
                else {
                    f[i][j]=max(f[i][j],max(f[i][k]*f[k+1][j],g[i][k]*g[k+1][j]));
                    g[i][j]=min(g[i][j],min(g[i][k]*g[k+1][j],min(g[i][k]*f[k+1][j],f[i][k]*g[k+1][j])));
                }
            }
    for(i=1,ans=-inf;i<=n;++i)
        ans=max(ans,f[i][i+n-1]);
    printf("%lld\n",ans);
    for(i=1;i<=n;++i)
        if(f[i][i+n-1]==ans) printf("%lld ",i);
    return putchar('\n'),0;
}

c. [√] pyramid

Title transfer

sol:

First, take into account the interval DP, so \ (f [l, r] \) represents the number of program sequences from l to r can be the tree of the composition.

So easy to think of the sub-tree is then split into two portions obtained by multiplying the result.

But this will be counted repeat, because the program turned around a way of dividing the order is likely to get another division scheme, and in fact consistent with both.

How to ensure no duplication of it?

Taking into account if there is a sub-tree has changed, then this tree is necessarily a new tree.

Therefore, it may be divided into the l ~ r ~ l + k-remaining portion. 1 a. 1 a subtree, k ~ r as a tree (a plurality of root subtree +), where k and l the same color.

In this case, an enumeration tree of subtrees becomes larger and larger, will not be repeated, by multiplying the two.

Therefore, the transfer equation:
\ [F [l, R & lt] F = [l +. 1,. 1-R & lt] + \ sum_ {l + 2≤k≤r-2, K l, and the same color} {f [l + 1 , k-1] * f [ k, r]} \ (l and r are the same color) \]
code:

#include<cmath>
#include<string>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define RG register
#define IL inline
#define LL long long
#define DB double
using namespace std;

IL int gi() {
   RG int x=0,w=0; char ch=getchar();
   while (ch<'0'||ch>'9') {if (ch=='-') w=1;ch=getchar();}
   while (ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar();
   return w?-x:x;
}

const int mod=1e9;

char s[303];
LL n,f[303][303];

LL solve(int l,int r) {
    if(l>r||s[l]!=s[r]) return 0;
    if(l==r) return f[l][r]=1;
    if(f[l][r]!=-1) return f[l][r];
    f[l][r]=solve(l+1,r-1);
    RG int i;
    for(i=l+2;i<=r-2;++i)
        if(s[l]==s[i]) f[l][r]=(f[l][r]+solve(l+1,i-1)*solve(i,r)%mod)%mod;
    return f[l][r];
}

int main()
{
    scanf("%s",s+1);
    n=1ll*strlen(s+1);
    memset(f,-1,sizeof(f));
    printf("%lld\n",solve(1,n));
    return 0;
}

d. [√] Course

Title transfer

sol:

Note that all courses constitute a forest, convenient transfer.

So it can separate a number 0 node, making it a rooted tree.

Then let \ (f [x, v] \) represents x number of courses to the total number of v choose the best credit.

Consider once every enumerate a son of x y, then the current optimal value of y necessarily constitute a part of a part of the sub-tree and sub-trees swept in before.

It can be found, in fact, these two values can be said to be known, in part \ (F [Y, P] \) , the other is \ (F [X, VP] \) . (Y p sub-trees selected course)

We should transfer equation:
\ [F [X, V] Y = max_ {\ in Son [X], v≥p≥0} \ lbrace {F [X, VP] + F [Y, P]} \ rbrace \]
However, since the current course x (in addition to node 0) must be selected, so there should be: \ (F [X, V] = F [X] [V-. 1] + a [X], V \ in (0, m] \) .

code:

#include<cmath>
#include<string>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define RG register
#define IL inline
#define LL long long
#define DB double
using namespace std;

IL int gi() {
   RG int x=0,w=0; char ch=getchar();
   while (ch<'0'||ch>'9') {if (ch=='-') w=1;ch=getchar();}
   while (ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar();
   return w?-x:x;
}

const int N=303;

int n,m,tot,a[N],f[N][N],head[N];

struct EDGE{int next,to;}e[N<<1];
IL void make(int x,int y) {e[++tot]=(EDGE){head[x],y},head[x]=tot;}

void DP(int x) {
    RG int i,j,k,y;
    for(i=head[x];i;i=e[i].next) {
        DP(y=e[i].to);
        for(j=m;j>=0;--j)  //必须倒序
            for(k=0;k<=j;++k) //此处似乎正倒序都可以
                f[x][j]=max(f[x][j],f[x][j-k]+f[y][k]);
    }
    if(!x) return;
    for(i=m;i>0;--i) f[x][i]=f[x][i-1]+a[x];
}

int main()
{
    RG int i,x;
    n=gi(),m=gi();
    for(i=1;i<=n;++i) x=gi(),a[i]=gi(),make(x,i);
    DP(0);
    printf("%d\n",f[0][m]);
    return 0;
}

e.[√]Accumulation Degree

Title transfer

sol:

Simple sol had written not write up.

Here

Guess you like

Origin www.cnblogs.com/Bhllx/p/10959105.html