bzoj2064 division (God-like pressure dp title)

Meaning of the questions:

1 an article to n1, n2 and an article 2, the required minimum number of operations, the article 2 into the article 1 (2 items can be split, may gather)

analysis:

A small range of data -> press or like violent search, search considered critical, memory status is not good, because the stitching together two articles will change the number of articles. So only consider like pressure. (Examination room half an hour when the pressure is extremely excited to play like, Wow I'm so smart, Wow I'm so strong, yeah actually play out , finally found the question wrong ... splitting items may have missed 2 to become article 1)

This is what I consider themselves very smart code (vomit)

#include<bits/stdc++.h>
using namespace std;
#define N 15
int n1,n2,a[N],b[N],dp[N][(1<<N)],pos[N];
int get(int x)
{
    int ans=0;
    while(x){ if(x&1) ans++; x>>=1; }
    return ans;
}
int check(int x,int y,int val)
{
    int rx=x,ry=y,cnt=0,wei=0,tot=0;
    while(ry){
        wei++;
        if((!(ry&1))&&(rx&1)) return -1;
        if((!(rx&1))&&(ry&1)) pos[++cnt]=wei;
        rx>>=1,ry>>=1;
    }
    for(int i=1;i<=cnt;i++) tot+=b[pos[i]];
    if(tot!=val) return -1;
    return cnt;
}
int main()
{
    freopen("Miku.in","r",stdin);
    freopen("Miku.out","w",stdout);
    scanf("%d",&n1);
    for(int i=1;i<=n1;i++) scanf("%d",&a[i]);
    scanf("%d",&n2);
    for(int i=1;i<=n2;i++) scanf("%d",&b[i]);
    if(n1==1) { printf("%d\n",n2-1); return 0 ; }
    memset(dp,0x7f7f7f,sizeof(dp));
    for(int i=0;i<(1<<n2);i++){
        int xx=check(i,(1<<n2)-1,a[1]);
        if(xx!=-1)
        dp[1][i]=xx-1;
    }
     
    for(int i=1;i<=n1-1;i++)
     for(int j=0;j<(1<<n2);j++) 
      for(int k=0;k<(1<<n2);k++){
          int xx=check(j,k,a[i+1]);
          if(get(j)<get(k)&&xx!=-1)
          dp[i+1][j]=min(dp[i+1][j],dp[i][k]+xx-1);
      }
    printf("%d\n",dp[n1][0]);
}
/*
4 5 3 6 4
7 2 3 4 3 4 1 1


ans 3
*/
SB wrote the wrong code

 

  So how dp Correct answer is it? The number of items gathered split frequently changing, no matter how good do not transfer title to go with the characteristics of nature.

  We can find (no, I did not find) , the highest operation count is the number of times after the n1 + n2-2 is to put it all gather and split. Then we found that, if the initial state k pick area just a state equal to the target block k2 area, we can make this alone a few k1 + k2-2 by operating target state is reached, the remaining n1-k1 and n2 -k2 can reach the target state split the merger, the total number of operational changes to n1 + n2-4 times, reduced twice. ( Reference )

  So we need to do is to find as many such relationships to reduce the frequency of use. N2 is set to a negative first article, sum the auxiliary array is not completed is recorded help from a k1 k2 spell, when the sum == 0, then the addition of a pair of the above-described relationship, the total number of operations can -2. The final answer is the total number of operations - can reduce the number of operations

 

#include<bits/stdc++.h>
using namespace std;
int n1,n2,a[30],sum[(1<<20)+5],dp[(1<<20)+5];
int main()
{
    freopen("Miku.in", "r", stdin);
    freopen("Miku.out", "w", stdout); 
    scanf("%d",&n1);
    for(int i=1;i<=n1;i++) scanf("%d",&a[i]);
    scanf("%d",&n2);
    for(int i=1;i<=n2;i++) scanf("%d",&a[i+n1]),a[i+n1]=-a[i+n1];
    int n=n1+n2;
    for(int i=1;i<(1<<n);i++){//1!!
     for(int j=1;j<=n;j++){
         if(i&(1<<j))//j xuan
         dp[i]=max(dp[i],dp[i^(1<<j)]),sum[i]+=a[j];
     }
         if(sum[i]==0)
           dp[i]++;
    }
    printf("%d\n",n-2*dp[(1<<n)-1]); 
}
/*
1 6
3 1 2 3
*/
Correct

 

Guess you like

Origin www.cnblogs.com/mowanying/p/11260707.html