题解:这题的数据被分成了2部分,我们分类讨论。①n<=40,我们分成前后2部分dfs;②n>40,发现c最大只有20000,所以dp即可。
代码如下:
1 #include<cstdio> 2 #include<iostream> 3 #define Mod 1000000007 4 #define MN 120000005 5 using namespace std; 6 int a[105],f[MN],ans,sum,n; 7 void rw(int&a,int b){if((a+=b)>=Mod) a-=Mod;} 8 void dfs1(int x,int nn,int k){ 9 if(k>sum) return; 10 if(x>nn){++f[k]; return;} 11 dfs1(x+1,nn,k); dfs1(x+1,nn,k+a[x]); 12 } 13 void dfs2(int x,int nn,int k){ 14 if(k>sum) return; 15 if(x>nn){rw(ans,f[sum-k]); return;} 16 dfs2(x+1,nn,k); dfs2(x+1,nn,k+a[x]); 17 } 18 int main() 19 { 20 freopen("promonkey.in","r",stdin); 21 freopen("promonkey.out","w",stdout); 22 scanf("%d",&n); 23 for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum+=a[i]; 24 if(sum%2==1){printf("0");return 0;} sum/=2; 25 if(n>40){ 26 f[0]=1; int x=0; 27 for(int i=1;i<=n;x+=a[i++]) 28 for(int j=min(sum,x);j>=0;j--) rw(f[j+a[i]],f[j]); 29 printf("%d",f[sum]); 30 return 0; 31 } 32 else{ 33 dfs1(1,n/2,0); dfs2(n/2+1,n,0); 34 printf("%d",ans); 35 return 0; 36 } 37 }
题解:我们二分答案,取向左和向右走的步数的最小值2倍数和最大值之和,若小于当前答案,继续向右拓展,这样如果最后所有的豆子都被吃则满足条件。
代码如下:
1 #include<cstdio> 2 #include<iostream> 3 #include<vector> 4 using namespace std; 5 vector<int> a,b; 6 int n,ans; 7 int calc(int l,int x,int r){ 8 int aa=x-l,bb=r-x; 9 return 2*min(aa,bb)+max(aa,bb); 10 } 11 bool check(int len){ 12 int i,j,L,R; 13 for(i=j=0;i<a.size();i++) 14 for(L=R=a[i];j<b.size();j++){ 15 if(calc(min(L,b[j]),a[i],max(R,b[j]))>len) break; 16 else L=min(L,b[j]),R=max(R,b[j]); 17 } 18 if(j<b.size()) return false; 19 return true; 20 } 21 int main() 22 { 23 freopen("pacman.in","r",stdin); 24 freopen("pacman.out","w",stdout); 25 scanf("%d\n",&n); 26 for(int i=1;i<=n;i++){ 27 char c; scanf("%c",&c); 28 if(c=='P') a.push_back(i); 29 if(c=='*') b.push_back(i); 30 } 31 int l=1,r=2*n; 32 while(l<=r){ 33 int mid=l+r>>1; 34 if(check(mid)) r=mid-1,ans=mid; 35 else l=mid+1; 36 } 37 printf("%d",ans); 38 }
题解:没写。