第一题 DP f[i][j]表示前i个数分成j堆的最小花费,f[i][j]=min{f[k][j-1]+(将i到k+1分别移动到i的花费)}

#include<fstream>
using namespace std;
ifstream cin("leaves.in");
ofstream cout("leaves.out");
int n,k;
int i,j;
int f[1010][11];
int a[1010],sum[1010],tot[1010];
int main()
{
    cin>>n>>k;
    for (i=1;i<=n;i++) cin>>a[i];
    for (i=1;i<=n;i++) {sum[i]=sum[i-1]+a[i];tot[i]=tot[i-1]+a[i]*(i-1);}
    memset(f,63,sizeof(f));
    for (i=1;i<=n;i++) f[i][1]=tot[i];
    for (j=2;j<=k;j++)
      for (i=j;i<=n;i++)
        for (int l=j-1;l<=i-1;l++)
          f[i][j]<?=f[l][j-1]+tot[i]-tot[l]-((sum[i]-sum[l])*l);
    cout<<f[n][k]<<endl;
    return 0;
}

第二题 归并排序求逆序对 要初始化

#include<fstream>
using namespace std;
ifstream cin("game.in");
ofstream cout("game.out");
int n,m,tot,num1,num2;
int a[40000],b[40000],c[40000],d[40000];
int s[250][250];
void msort1(int l,int r)
{
     int i,j,k,m;
     if (l>=r) return;
     m=(l+r)>>1;
     msort1(l,m);
     msort1(m+1,r);
     i=l;j=m+1;k=l;
     do
     {
       if (a[i]>a[j])
       {
         num1+=(m-i+1);
         c[k]=a[j];
         j++;k++;
       }
       else 
       {
            c[k]=a[i];i++;k++;
       }
     }while (i<=m&&j<=r);
     while (i<=m) {c[k]=a[i];k++;i++;}
     while (j<=r) {c[k]=a[j];k++;j++;}
     for (i=l;i<=r;i++) a[i]=c[i];  
}
void msort2(int l,int r)
{
     int i,j,k,m;
     if (l>=r) return;
     m=(l+r)>>1;
     msort2(l,m);
     msort2(m+1,r);
     i=l;j=m+1;k=l;
     do
     {
       if (b[i]>b[j])
       {
         num2+=(m-i+1);
         d[k]=b[j];
         j++;k++;
       }
       else 
       {
            d[k]=b[i];i++;k++;
       }
     }while (i<=m&&j<=r);
     while (i<=m) {d[k]=b[i];k++;i++;}
     while (j<=r) {d[k]=b[j];k++;j++;}
     for (i=l;i<=r;i++) b[i]=d[i];
}


int main()
{
    int i,j;
    while (cin>>n>>m)
    {
          num1=0;num2=0;
          for (i=1;i<=n;i++)
          for (j=1;j<=n;j++)
            cin>>s[i][j];
          tot=0;
          for (i=1;i<=n;i++)
          for (j=1;j<=n;j++)
          {
              a[++tot]=s[i][j];
          }
          tot=0;
          for (i=1;i<=n;i++)
          for (j=1;j<=n;j++)
          {
              b[++tot]=s[j][i];
          }
          msort1(1,tot);
          msort2(1,tot);
          if (num1==num2) {cout<<"NYY and XYY will try again"<<endl;cout<<endl;continue;}
          if (m%2==1) 
          {
                      if (num1<num2) {cout<<"NYY wins the Rocket's Game"<<endl;cout<<endl;continue;}
                      else {cout<<"XYY wins the Rocket's Game"<<endl;cout<<endl;continue;}
          }
          else 
          {
               if (num1>num2) {cout<<"NYY wins the Rocket's Game"<<endl;cout<<endl;continue;}
                      else {cout<<"XYY wins the Rocket's Game"<<endl;cout<<endl;continue;}
          }
    }
    return 0;
}

第三题 两次dfs过程

#include<fstream>
using namespace std;
ifstream cin("simple.in");
ofstream cout("simple.out");
struct node
{
       int x,n;
}e[200000];
int k[1000],d[1000];
int n,m,o=0,ans=0,num;
bool v[1000];
int i,j;
void add(int x,int y)
{
     e[++o].x=y;
     e[o].n=k[x];
     k[x]=o;
}
void dfs(int x)
{
     int t=k[x];
     while (t)
     {
           if (e[t].x==i) d[i]++;
           if (!v[e[t].x])
           {
                          v[e[t].x]=true;
                          dfs(e[t].x);
           };
           t=e[t].n;
     }
}
void find(int x)
{
     int t=k[x];
     while (t)
     {
           num>?=d[e[t].x];
           if (!v[e[t].x])
           {
                          v[e[t].x]=true;
                          find(e[t].x);
           };
           t=e[t].n;
     }
}
int main()
{
    cin>>n>>m;
    int x,y;
    for (i=1;i<=m;i++)
    {
        cin>>x>>y;
        add(x,y);
        add(y,x);
    }
    for (i=1;i<=n;i++)
    {
        v[i]=true;
        int t=k[i];
        while(t)
        {
                if (!v[e[t].x]) 
                {
                                v[e[t].x]=true;
                                dfs(e[t].x);
                                d[i]--;
                }
                t=e[t].n;
        }
        memset(v,0,sizeof(v));
    }
    for (i=1;i<=n;i++)
    if (!v[i])
    {
              num=0;
              v[i]=true;
              find(i);
              ans+=(num<2);
    }
    cout<<ans<<endl;
    return 0;
}

第四题 树形DP f[i][k]>?=f[i][j]+f[s][k-j] s是i的子节点

#include<fstream>
using namespace std;
ifstream cin("tele.in");
ofstream cout("tele.out");
int n,m,o;
struct node
{
       int x,y,n;
}e[5000];
int k[3010];
int f[3010][3010],g[3010];
void add(int x,int y,int z)
{
     e[++o].x=y;
     e[o].y=z;
     e[o].n=k[x];
     k[x]=o;
}
int dp(int x)
{
     int t,num=0;
     t=k[x];
     if (!t)
     {
            f[x][1]=g[x];
            return 1;
     }
     while (t)
     {
           int p=dp(e[t].x);
           num+=p;
           for (int k=num;k>0;k--)
             for (int j=1;j<=min(k,p);j++)
               f[x][k]>?=f[x][k-j]+f[e[t].x][j]-e[t].y;
           t=e[t].n;
     }
     return num;
}

int main()
{
    int i,j,x,y;
    cin>>n>>m;
    for (i=1;i<=n-m;i++)
    {
        int t;
        cin>>t;
        for (j=1;j<=t;j++)
        {
            cin>>x>>y;
            add(i,x,y);
        }
    }
    for (i=n-m+1;i<=n;i++) cin>>g[i];
    memset(f,128,sizeof(f));
    for (i=1;i<=n;i++) f[i][0]=0;
    j=dp(1);
    int temp=m;
    while (f[1][temp]<0) temp--;
    cout<<temp<<endl;
    return 0;
}