Minieye杯第十五届华中科技大学程序设计邀请赛网络赛 部分题目
链接:https://pan.baidu.com/s/12gSzPHEgSNbT5Dl2QqDNpA
提取码:fw39
复制这段内容后打开百度网盘手机App,操作更方便哦
D Grid
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <set> 8 #include <map> 9 #include <queue> 10 #include <iostream> 11 using namespace std; 12 13 #define ll long long 14 15 const int maxn=2e2+10; 16 const int inf=1e9; 17 const double eps=1e-8; 18 19 char s[maxn][maxn]; 20 21 int main() 22 { 23 int h,w,n,m,i,j,x,y; 24 scanf("%d%d%d",&h,&w,&n); 25 m=(h*w+1)/2; 26 if (n>m) 27 printf("-1"); 28 else 29 { 30 for (i=0;i<h;i++) 31 for (j=0;j<w;j++) 32 s[i][j]='*'; 33 x=0,y=0; 34 while (n--) 35 { 36 s[x][y]='#'; 37 y+=2; 38 if (y>=w) 39 { 40 x++; 41 if (s[x-1][0]=='#') 42 y=1; 43 else 44 y=0; 45 } 46 } 47 for (i=0;i<h;i++) 48 { 49 for (j=0;j<w;j++) 50 printf("%c",s[i][j]); 51 printf("\n"); 52 } 53 } 54 return 0; 55 } 56 /* 57 58 */
G Multithread
模拟
inf long long
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <set> 8 #include <map> 9 #include <queue> 10 #include <iostream> 11 using namespace std; 12 13 #define ll long long 14 15 const int maxn=1e6+10; 16 const ll inf=1e18; 17 const double eps=1e-15; 18 19 ll a[maxn],c[maxn],t=0; 20 21 int main() 22 { 23 int n,i,j; 24 double z; 25 scanf("%d",&n); 26 for (i=1;i<=n;i++) 27 scanf("%lld",&a[i]); 28 sort(a+1,a+n+1); 29 a[n+1]=inf; 30 j=1; 31 for (i=1;i<=n;i++) 32 { 33 while (a[j]==a[i]) 34 j++; 35 c[i]=a[j]; 36 } 37 for (i=1;i<=n;i++) 38 { 39 t=max(t,a[i]); 40 if (t>=c[i]) 41 { 42 printf("0"); 43 return 0; 44 } 45 t+=ceil(sqrt(a[i])); 46 } 47 printf("1"); 48 return 0; 49 } 50 /* 51 4 52 10 11 17 18 53 54 4 55 10 11 18 18 24 56 57 5 58 0 0 0 3 4 59 60 10 61 1000000000 1000000000 1000000000 1000000000 1000000000 62 1000000000 1000000000 1000000000 1000000000 1000000000 63 */
I Tree
贪心,一颗子树的权值和大于某个值则使用该子树,否则该子树必定被子树根的父亲使用。
其实上界可以为sum(c[i])/k,但二分,也节省不了几次操作。
注意long long,莫名其妙地使用“ll*”失效了,所以我输入的变量的类型设置为long long。
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <set> 8 #include <map> 9 #include <queue> 10 #include <iostream> 11 using namespace std; 12 13 #define ll long long 14 15 const int maxn=1e5+10; 16 const int inf=1e9; 17 const double eps=1e-8; 18 19 struct node 20 { 21 int d; 22 node *to; 23 }*e[maxn]; 24 25 ll c[maxn],sum[maxn],m; 26 bool vis[maxn]; 27 int g=0; 28 29 void dfs(int d) 30 { 31 vis[d]=1; 32 node *p=e[d]; 33 sum[d]+=c[d]; 34 while (p) 35 { 36 if (!vis[p->d]) 37 { 38 dfs(p->d); 39 sum[d]+=sum[p->d]; 40 } 41 p=p->to; 42 } 43 if (sum[d]>=m) 44 g++,sum[d]=0; 45 } 46 47 int main() 48 { 49 node *p; 50 int x,y,i; 51 ll n,k,l,r; 52 scanf("%lld%lld",&n,&k); 53 for (i=1;i<n;i++) 54 { 55 scanf("%d%d",&x,&y); 56 p=new node(); 57 p->d=y; 58 p->to=e[x]; 59 e[x]=p; 60 61 p=new node(); 62 p->d=x; 63 p->to=e[y]; 64 e[y]=p; 65 } 66 for (i=1;i<=n;i++) 67 scanf("%lld",&c[i]); 68 l=1,r=100000*n/k; 69 while (l<=r) 70 { 71 m=(l+r)>>1; 72 g=0; 73 memset(vis,0,sizeof(vis)); 74 memset(sum,0,sizeof(sum)); 75 dfs(1); 76 if (g>=k) 77 l=m+1; 78 else 79 r=m-1; 80 } 81 printf("%lld",r); 82 return 0; 83 } 84 /* 85 5 5 86 1 2 87 1 3 88 2 4 89 2 5 90 4 4 3 4 5 91 */
K Car
注意x,y的作用域,减少了不少方案。
还是那样,想清楚了再编码,验证一下测试样例,造多几个数据。
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <set> 8 #include <map> 9 #include <queue> 10 #include <iostream> 11 using namespace std; 12 13 #define ll long long 14 15 const int maxn=1e6+10; 16 const int inf=1e9; 17 const double eps=1e-8; 18 19 ll f[maxn][2]; 20 21 int main() 22 { 23 char ch; 24 ll a,b,c,d,x=0,y=0,sum=0,v=1<<30; 25 int n,i; 26 bool vis=0; 27 scanf("%d",&n); 28 for (i=1;i<=n;i++) 29 { 30 scanf("\n%c",&ch); 31 if (ch=='C') 32 { 33 scanf("%lld%lld%lld%lld",&a,&b,&c,&d); 34 sum+=(y+b)*v*2; 35 sum-=b*(v-(x+a)); 36 x+=a-c; 37 y+=b-d; 38 sum-=d*(x+v); 39 vis=1; 40 } 41 else 42 { 43 scanf("%lld%lld",&a,&b); 44 if (!vis) 45 { 46 if (i&1) 47 x+=a; 48 else 49 x-=a; 50 sum-=(v-x)*b; 51 y+=b; 52 } 53 else 54 { 55 if (i&1) 56 x-=a; 57 else 58 x+=a; 59 sum-=(x+v)*b; 60 y-=b; 61 } 62 } 63 } 64 printf("%lld",sum); 65 return 0; 66 } 67 /* 68 4 69 C 10 10 15 3 70 B 2 5 71 A 3 1 72 B 6 1 73 74 4 75 C 10 10 15 20 76 A 10 2 77 B 6 3 78 A 1 5 79 80 3 81 B 100 60 82 A 30 10 83 C 50 200 120 30 84 85 4 86 A 100 60 87 B 30 50 88 C 90 700 170 800 89 B 10 10 90 */
J Another Easy Problem
比赛时暴力了一发,感觉数值在[1,50]范围内,结果不会太大。看了一下数据,果然,结果<=5,但时间上仍然承受不了。
方法比较巧妙。其实这种题,要养成往dp想的习惯。。。
dp,差值可以选择用绝对值表示,因为sum(a[i])<=5000,所以途中,差值最多不超过2500,否则无法再‘’追‘’回来,使差值为0。而数组的第一维,可以使用滚动数组,数组的第二维,其实最多可以开到2500+50即可。
\( i为已判断i个数,j为差值 f[i][j]为对应的最小未使用数字个数\\f[i][j]=min(f[i-1][j]+1,min(f[i-1][j+a],f[i-1][abs(j-a)]) \)
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <set> 8 #include <map> 9 #include <queue> 10 #include <iostream> 11 using namespace std; 12 13 #define ll long long 14 15 const int maxn=1e2+10; 16 const int maxm=5e3+10; 17 const int inf=1e9; 18 const double eps=1e-8; 19 20 int f[maxn][maxm]; 21 22 int main() 23 { 24 int t,n,a,i,j; 25 scanf("%d",&t); 26 while (t--) 27 { 28 memset(f,0x3f,sizeof(f)); 29 f[0][0]=0; 30 scanf("%d",&n); 31 for (i=1;i<=n;i++) 32 { 33 scanf("%d",&a); 34 for (j=0;j<=2500;j++) 35 f[i][j]=min(f[i-1][j]+1,min(f[i-1][j+a],f[i-1][abs(j-a)])); 36 } 37 printf("%d\n",f[n][0]); 38 } 39 return 0; 40 } 41 /* 42 5 43 1 2 4 8 16 44 45 5 46 1 10 11 30 49 47 */
B Balls
比赛时考虑到与数学推导有关,没仔细想。
比赛时应该打表找规律的。哎,其它题写太卡了,耗费大量时间。
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <set> 8 #include <map> 9 #include <queue> 10 #include <iostream> 11 using namespace std; 12 13 #define ll long long 14 15 const int maxn=1e4+10; 16 const int inf=1e9; 17 const double eps=1e-8; 18 ll sum=0; 19 20 void dfs(int k,int s,ll v) 21 { 22 if (k==0) 23 // { 24 // printf("%lld ",v); 25 sum+=v; 26 // } 27 28 else 29 { 30 for (int i=s-k+1;i>=1;i--) 31 dfs(k-1,s-i,v*i); 32 } 33 } 34 35 int main() 36 { 37 int k,s; 38 // scanf("%d%d",&k,&s); 39 for (k=1;k<=10;k++) 40 for (s=1;s<=10;s++) 41 { 42 sum=0; 43 dfs(k,s,1); 44 printf("%4lld",sum); 45 if (s==10) 46 printf("\n"); 47 else 48 printf(" "); 49 } 50 return 0; 51 } 52 /* 53 54 */
如果不熟悉,再打一个组合数学的表。
方法挺巧妙的!组合数学。
lucas,直接求逆超时了,求逆初始化,参见代码。
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <set> 8 #include <map> 9 #include <queue> 10 #include <iostream> 11 using namespace std; 12 13 #define ll long long 14 15 const int maxn=5e6+10; 16 const int inf=1e9; 17 const double eps=1e-8; 18 19 ll p,mul[maxn],chu[maxn]; 20 21 ll pow(ll a,ll b) 22 { 23 ll y=1; 24 while (b) 25 { 26 if (b & 1) 27 y=y*a%p; 28 a=a*a%p; 29 b>>=1; 30 } 31 return y; 32 } 33 34 ll cal(ll n,ll m) 35 { 36 if (n<m) 37 return 0; 38 ll y=1,i; 39 if (m+m>n) 40 m=n-m; 41 return mul[n]*chu[n-m]%p*chu[m]%p; 42 // for (i=1;i<=m;i++) 43 // y=y*(n+1-i)%p*pow(i,p-2)%p; 44 return y; 45 } 46 47 int main() 48 { 49 ll n,m,r,i; 50 scanf("%lld%lld%lld",&m,&n,&p); 51 ///init 52 mul[0]=1; 53 for (i=1;i<p;i++) 54 mul[i]=mul[i-1]*i%p; 55 chu[p-1]=pow(mul[p-1],p-2); 56 for (i=p-2;i>=1;i--) 57 chu[i]=chu[i+1]*(i+1)%p; 58 59 n+=m,m*=2; 60 r=1; 61 while (m) 62 { 63 r=r*cal(n%p,m%p)%p; 64 n/=p,m/=p; 65 } 66 printf("%lld",r); 67 return 0; 68 } 69 /* 70 71 */
E Lolita Dress
组合公式变形
\( \begin{equation*}\begin{split}&\sum_{n=1}^{min(x,y)}(C_{x}^{n-1}*C_{y}^{n}) \\&=\sum_{n=1}^{min(x,y)}(C_{x}^{x-n+1}*C_{y}^{n}) \\&=C_{x+y}^{x+1}\end{split}\end{equation*} \)
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <set> 8 #include <map> 9 #include <queue> 10 #include <iostream> 11 using namespace std; 12 13 #define ll long long 14 15 const int maxn=1e6+10; 16 const int inf=1e9; 17 const double eps=1e-8; 18 const ll mod=1e9+7; 19 20 int a[maxn]; 21 ll mul[maxn],chu[maxn]; 22 23 ll pow(ll a,ll b) 24 { 25 ll y=1; 26 while (b) 27 { 28 if (b&1) 29 y=y*a%mod; 30 a=a*a%mod; 31 b>>=1; 32 } 33 return y; 34 } 35 36 ll cal(ll x,ll y) 37 { 38 return mul[x]*chu[y]%mod*chu[x-y]%mod; 39 } 40 41 int main() 42 { 43 ll sum=0; 44 int n,x=0,y=0,i; 45 scanf("%d",&n); 46 mul[0]=1; 47 for (i=1;i<=n;i++) 48 mul[i]=mul[i-1]*i%mod; 49 chu[n]=pow(mul[n],mod-2); 50 for (i=n-1;i>=0;i--) 51 chu[i]=chu[i+1]*(i+1)%mod; 52 53 for (i=1;i<=n;i++) 54 { 55 scanf("%d",&a[i]); 56 if (a[i]) 57 y++; 58 } 59 for (i=1;i<=n;i++) 60 if (a[i]==0) 61 { 62 sum=(sum+cal(x+y,x+1))%mod; 63 x++; 64 } 65 else 66 y--; 67 printf("%lld",sum); 68 return 0; 69 } 70 /* 71 72 */
A Wormhole Construction
之前理解错题意了,只需要求最小的d,不需要最佳的方案(最小边)
打表找规律
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <set> 8 #include <map> 9 #include <queue> 10 #include <iostream> 11 using namespace std; 12 13 #define ll long long 14 15 const int maxn=20; 16 const int inf=1e9; 17 const double eps=1e-8; 18 19 int n,r; 20 21 struct node 22 { 23 int a[maxn][maxn]; 24 node() 25 { 26 int i,j; 27 for (i=1;i<=n;i++) 28 for (j=1;j<=n;j++) 29 a[i][j]=0; 30 } 31 node operator*(node y) 32 { 33 node z=*this; 34 int i,j,k; 35 for (k=1;k<=n;k++) 36 for (i=1;i<=n;i++) 37 for (j=1;j<=n;j++) 38 z.a[i][j]|=a[i][k]*y.a[k][j]; 39 return z; 40 } 41 int work() 42 { 43 node z; 44 int i,j,l; 45 z=*this; 46 for (l=1;l<n;l++) 47 { 48 z=z*(*this); 49 j=1; 50 for (i=1;i<=n;) 51 { 52 if (i!=j && z.a[i][j]==0) 53 break; 54 if (j==n) 55 i++,j=1; 56 else 57 j++; 58 } 59 if (i==n+1) 60 return l; 61 } 62 return n; 63 } 64 }mat,result; 65 66 void build(int i,int j) 67 { 68 int k,v; 69 ///guess, fasten the speed 70 // if (r==2) 71 // return; 72 for (k=1;k>=0;k--) 73 { 74 if (k==1 && (i==j || mat.a[j][i]==1)) 75 continue; 76 mat.a[i][j]=k; 77 if (j==n) 78 { 79 if (i==n) 80 { 81 v=mat.work()+1; 82 ///observe 83 if (n>=5 && v==2) 84 { 85 for (int u=1;u<=n;u++) 86 { 87 for (int v=1;v<=n;v++) 88 printf("%d ",mat.a[u][v]); 89 printf("\n"); 90 } 91 printf("\n"); 92 } 93 if (v<r) 94 { 95 r=v; 96 result=mat; 97 } 98 99 return; 100 } 101 build(i+1,1); 102 } 103 else 104 build(i,j+1); 105 } 106 } 107 108 int main() 109 { 110 for (n=3;n<=10;n++) 111 { 112 r=n; 113 build(1,1); 114 printf("%d : %d\n",n,r); 115 // for (int i=1;i<=n;i++) 116 // { 117 // for (int j=1;j<=n;j++) 118 // printf("%d ",result.a[i][j]); 119 // printf("\n"); 120 // } 121 } 122 return 0; 123 } 124 /* 125 3 : 2 126 0 1 0 127 0 0 1 128 1 0 0 129 4 : 3 130 0 1 1 0 131 0 0 1 1 132 0 0 0 1 133 1 0 0 0 134 5 : 2 135 0 1 1 1 0 136 0 0 1 0 1 137 0 0 0 1 1 138 0 1 0 0 1 139 1 0 0 0 0 140 6 : 2 141 0 1 1 1 0 0 142 0 0 1 1 1 0 143 0 0 0 1 0 1 144 0 0 0 0 1 1 145 1 0 1 0 0 1 146 1 1 0 0 0 0 147 7 : 2 148 0 1 1 1 1 1 0 149 0 0 1 1 1 0 1 150 0 0 0 1 0 1 1 151 0 0 0 0 1 1 1 152 0 0 1 0 0 1 1 153 0 1 0 0 0 0 1 154 1 0 0 0 0 0 0 155 7 several minutes 156 */
就能发现除了4之外,其它的答案都是2。
就能发现两个比较有意思的解法(当然,这是在已经答案的基础上,尴尬。。。)
0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 0 1 0 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 0 1 1 0 0 0 0 0 1 1 0 0 1 0 0 0 1 0
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <set> 8 #include <map> 9 #include <queue> 10 #include <iostream> 11 using namespace std; 12 13 #define ll long long 14 15 const int maxn=1e4+10; 16 const int inf=1e9; 17 const double eps=1e-8; 18 19 20 21 int main() 22 { 23 int n,m,i,j,k; 24 scanf("%d",&n); 25 if (n==4) 26 { 27 printf("3 4\n1 2\n2 3\n3 4\n4 1"); 28 return 0; 29 } 30 31 if (n&1) 32 { 33 m=n>>1; 34 printf("2 %d\n",n*m); 35 for (i=1;i<=n;i++) 36 for (j=1;j<=m;j++) 37 { 38 k=i+j; 39 if (k>n) 40 k-=n; 41 printf("%d %d\n",i,k); 42 } 43 } 44 else 45 { 46 m=(n-1)>>1; 47 printf("2 %d\n",(n-1)*m+4); 48 for (i=2;i<=n;i++) 49 for (j=1;j<=m;j++) 50 { 51 k=i+j; 52 if (k>n) 53 k-=n-1; 54 printf("%d %d\n",i,k); 55 } 56 printf("%d %d\n",1,2); 57 printf("%d %d\n",1,2+m+1); 58 printf("%d %d\n",3,1); 59 printf("%d %d\n",3+m+1,1); 60 } 61 return 0; 62 } 63 /* 64 65 */
O((n*n/2)*n*n*(2m))
(n*n/2) [i,j]区间
n [i,j]区间中任意一点 被多算
2m 可以取到的值
事实上,n中取任意三点,n*(n-1)*(n-2)/6
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <set> 8 #include <map> 9 #include <queue> 10 #include <iostream> 11 using namespace std; 12 13 #define ll long long 14 15 const int maxn=32; ///pay attention 16 const int maxm=4e3+10; ///2*m 17 const int inf=1e9; 18 const double eps=1e-8; 19 20 struct node1 21 { 22 int l,r,x,y; 23 bool operator<(const node1 &b) 24 { 25 return l<b.l; 26 } 27 }s1[maxm]; 28 29 struct node2 30 { 31 int l,r,x,y; 32 bool operator<(const node2 &b) 33 { 34 return r<b.r; 35 } 36 }s2[maxm]; 37 38 int f[maxn][maxn][maxm],temp[maxn][maxn][maxm],v[maxm],vv[maxm]; 39 int pref[maxn][maxn][maxm],pret[maxn][maxn][maxm],re[maxn],vs[maxm],vt[maxm]; 40 int add[maxm],fan[500000+10]; 41 42 void findarr(int i,int j,int g) 43 { 44 re[pref[i][j][g]]=v[g]; 45 if (i<=pref[i][j][g]-1) 46 findarr(i , pref[i][j][g]-1 , pret[i][ pref[i][j][g]-1 ][g]); 47 if (pref[i][j][g]+1<=j) 48 findarr(pref[i][j][g]+1 , j , pret[ pref[i][j][g]+1 ][j][g]); 49 } 50 51 int main() 52 { 53 int n,m,g=0,l,r,x,y,c,i,j,k,s,t,value,cnt,sum; 54 scanf("%d%d",&n,&m); 55 for (i=1;i<=m;i++) 56 { 57 scanf("%d%d%d%d",&l,&r,&x,&y); 58 vv[i*2-1]=x,vv[i*2]=y; 59 s1[i]={l,r,x,y}; 60 s2[i]={l,r,x,y}; 61 } 62 sort(vv+1,vv+m*2+1); ///m*2 63 vv[0]=vv[1]-1; 64 for (i=1;i<=m*2;i++) 65 if (vv[i]!=vv[i-1]) 66 v[++g]=vv[i]; 67 for (i=1;i<=g;i++) 68 fan[v[i]]=i; 69 sort(s1+1,s1+m+1); 70 sort(s2+1,s2+m+1); 71 s1[m+1].l=-1,s2[m+1].r=-1; 72 j=1; 73 for (i=1;i<=n;i++) ///n 74 { 75 vs[i]=j; 76 while (s1[j].l==i) 77 j++; 78 } 79 j=1; 80 for (i=1;i<=n;i++) 81 { 82 vt[i]=j; 83 while (s2[j].r==i-1) 84 j++; 85 } 86 87 memset(f,0xff,sizeof(f));///-1 88 for (c=0;c<n;c++) 89 for (i=1,j=c+i;j<=n;i++,j++) 90 { 91 cnt=0; 92 ///l~r,值为v。一开始数量是0,l从左到右,遇到左端点(排序),若右端点小于等于r,且v in [x,y],加1;遇到右端点(排序),若左端点大于等于l,且v in [x,y],减1。 93 s=vs[i]; 94 t=vt[i]; 95 // if (i==2 && j==5) 96 // { 97 // printf("z"); 98 // } 99 memset(add,0,sizeof(add)); 100 for (l=i;l<=j;l++) 101 { 102 ///[i,l) (l,j] 103 ///interval[x,y] i<=x<=l l<=y<=j 104 while (s1[s].l==l) 105 { 106 if (s1[s].r<=j) 107 add[fan[s1[s].x]]++,add[fan[s1[s].y]+1]--; 108 s++; 109 } 110 while (s2[t].r==l-1) 111 { 112 if (s2[t].l>=i) 113 add[fan[s2[t].x]]--,add[fan[s2[t].y]+1]++; 114 t++; 115 } 116 cnt=0; 117 for (k=1;k<=g;k++) 118 { 119 cnt+=add[k]; 120 value=temp[i][l-1][k]+temp[l+1][j][k]+cnt*v[k]; 121 if (value>f[i][j][k]) 122 { 123 f[i][j][k]=value; 124 pref[i][j][k]=l; 125 } 126 // f[i][j][k]=max(f[i][j][k],temp[i][l][k]+temp[l+1][j][k]+cnt*v[k]); 127 } 128 } 129 temp[i][j][g]=f[i][j][g]; 130 pret[i][j][g]=g; 131 for (k=g-1;k>=1;k--) 132 { 133 if (temp[i][j][k+1]>f[i][j][k]) 134 { 135 temp[i][j][k]=temp[i][j][k+1]; 136 pret[i][j][k]=pret[i][j][k+1]; 137 } 138 else 139 { 140 temp[i][j][k]=f[i][j][k]; 141 pret[i][j][k]=k; 142 } 143 // temp[i][j][k]=max(temp[i][j][k+1],f[i][j][k]); 144 } 145 } 146 sum=0; 147 for (i=1;i<=g;i++) 148 if (f[1][n][i]>sum) 149 sum=f[1][n][i],j=i; 150 // sum=max(sum,f[1][n][i]); 151 printf("%d\n",sum); 152 findarr(1,n,j); 153 for (i=1;i<=n;i++) 154 printf("%d%c",re[i],i==n?'\n':' '); 155 return 0; 156 } 157 /* 158 5 1 159 2 4 15 20 160 161 5 2 162 1 3 5 10 163 4 5 2 4 164 165 5 2 166 1 5 10 15 167 1 5 5 8 168 169 5 2 170 1 4 10 15 171 2 3 5 8 172 173 5 2 174 1 4 5 8 175 2 3 10 15 176 177 5 4 178 1 3 5 7 179 2 4 7 8 180 3 5 9 9 181 1 4 4 5 182 183 5 5 184 1 2 3 5 185 2 3 4 6 186 3 4 2 5 187 4 5 3 4 188 1 5 7 8 189 */
超时代码:处理cnt不当
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <set> 8 #include <map> 9 #include <queue> 10 #include <iostream> 11 using namespace std; 12 13 #define ll long long 14 15 const int maxn=32; ///pay attention 16 const int maxm=4e3+10; ///2*m 17 const int inf=1e9; 18 const double eps=1e-8; 19 20 struct node1 21 { 22 int l,r,x,y; 23 bool operator<(const node1 &b) 24 { 25 return l<b.l; 26 } 27 }s1[maxm]; 28 29 struct node2 30 { 31 int l,r,x,y; 32 bool operator<(const node2 &b) 33 { 34 return r<b.r; 35 } 36 }s2[maxm]; 37 38 int f[maxn][maxn][maxm],temp[maxn][maxn][maxm],v[maxm],vv[maxm]; 39 int pref[maxn][maxn][maxm],pret[maxn][maxn][maxm],re[maxn],vs[maxm],vt[maxm]; 40 41 void findarr(int i,int j,int g) 42 { 43 re[pref[i][j][g]]=v[g]; 44 if (i<=pref[i][j][g]-1) 45 findarr(i , pref[i][j][g]-1 , pret[i][ pref[i][j][g]-1 ][g]); 46 if (pref[i][j][g]+1<=j) 47 findarr(pref[i][j][g]+1 , j , pret[ pref[i][j][g]+1 ][j][g]); 48 } 49 50 int main() 51 { 52 int n,m,g=0,l,r,x,y,c,i,j,k,s,t,value,cnt,sum; 53 scanf("%d%d",&n,&m); 54 for (i=1;i<=m;i++) 55 { 56 scanf("%d%d%d%d",&l,&r,&x,&y); 57 vv[i*2-1]=x,vv[i*2]=y; 58 s1[i]={l,r,x,y}; 59 s2[i]={l,r,x,y}; 60 } 61 sort(vv+1,vv+m*2+1); ///m*2 62 vv[0]=vv[1]-1; 63 for (i=1;i<=m*2;i++) 64 if (vv[i]!=vv[i-1]) 65 v[++g]=vv[i]; 66 sort(s1+1,s1+m+1); 67 sort(s2+1,s2+m+1); 68 s1[m+1].l=-1,s2[m+1].r=-1; 69 j=1; 70 for (i=1;i<=n;i++) ///n 71 { 72 vs[i]=j; 73 while (s1[j].l==i) 74 j++; 75 } 76 j=1; 77 for (i=1;i<=n;i++) 78 { 79 vt[i]=j; 80 while (s2[j].r==i-1) 81 j++; 82 } 83 84 memset(f,0xff,sizeof(f));///-1 85 for (c=0;c<n;c++) 86 for (i=1,j=c+i;j<=n;i++,j++) 87 { 88 for (k=1;k<=g;k++) 89 { 90 cnt=0; 91 ///l~r,值为v。一开始数量是0,l从左到右,遇到左端点(排序),若右端点小于等于r,且v in [x,y],加1;遇到右端点(排序),若左端点大于等于l,且v in [x,y],减1。 92 s=vs[i]; 93 t=vt[i]; 94 // if (i==1 && j==4 && k==4) 95 // { 96 // printf("z"); 97 // } 98 for (l=i;l<=j;l++) 99 { 100 ///[i,l) (l,j] 101 ///interval[x,y] i<=x<=l l<=y<=j 102 while (s1[s].l==l) 103 { 104 if (s1[s].r<=j && s1[s].x<=v[k] && v[k]<=s1[s].y) 105 cnt++; 106 s++; 107 } 108 while (s2[t].r==l-1) 109 { 110 if (s2[t].l>=i && s2[t].x<=v[k] && v[k]<=s2[t].y) 111 cnt--; 112 t++; 113 } 114 value=temp[i][l-1][k]+temp[l+1][j][k]+cnt*v[k]; 115 if (value>f[i][j][k]) 116 { 117 f[i][j][k]=value; 118 pref[i][j][k]=l; 119 } 120 // f[i][j][k]=max(f[i][j][k],temp[i][l][k]+temp[l+1][j][k]+cnt*v[k]); 121 } 122 } 123 temp[i][j][g]=f[i][j][g]; 124 pret[i][j][g]=g; 125 for (k=g-1;k>=1;k--) 126 { 127 if (temp[i][j][k+1]>f[i][j][k]) 128 { 129 temp[i][j][k]=temp[i][j][k+1]; 130 pret[i][j][k]=pret[i][j][k+1]; 131 } 132 else 133 { 134 temp[i][j][k]=f[i][j][k]; 135 pret[i][j][k]=k; 136 } 137 // temp[i][j][k]=max(temp[i][j][k+1],f[i][j][k]); 138 } 139 } 140 sum=0; 141 for (i=1;i<=g;i++) 142 if (f[1][n][i]>sum) 143 sum=f[1][n][i],j=i; 144 // sum=max(sum,f[1][n][i]); 145 printf("%d\n",sum); 146 findarr(1,n,j); 147 for (i=1;i<=n;i++) 148 printf("%d%c",re[i],i==n?'\n':' '); 149 return 0; 150 } 151 /* 152 5 1 153 2 4 15 20 154 155 5 2 156 1 3 5 10 157 4 5 2 4 158 159 5 2 160 1 5 10 15 161 1 5 5 8 162 163 5 2 164 1 4 10 15 165 2 3 5 8 166 167 5 2 168 1 4 5 8 169 2 3 10 15 170 171 5 4 172 1 3 5 7 173 2 4 7 8 174 3 5 9 9 175 1 4 4 5 176 177 5 5 178 1 2 3 5 179 2 3 4 6 180 3 4 2 5 181 4 5 3 4 182 1 5 7 8 183 */
去年
01背包,size,value, Totsize, solve maxValue。
空间太大,转变为以价值作为一维
\( v为当前的总价值,f[v]为对应的最小使用空间\\ f[v]=min(f[v],f[v-size_{i}]+cost_{i}) \)
O(sum(value)*n)
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <set> 8 #include <map> 9 #include <queue> 10 #include <iostream> 11 using namespace std; 12 13 #define ll long long 14 15 const int maxn=1e4+10; 16 const int inf=1e9; 17 const double eps=1e-8; 18 19 int f[maxn]; 20 21 int main() 22 { 23 int t,n,m,i,j,a,b,tot; 24 scanf("%d",&t); 25 while (t--) 26 { 27 memset(f,0x3f,sizeof(f)); 28 scanf("%d%d",&n,&m); 29 f[0]=0; 30 tot=0; 31 while (n--) 32 { 33 scanf("%d%d",&a,&b); 34 tot+=b; 35 for (j=tot;j>=b;j--) 36 f[j]=min(f[j],f[j-b]+a); 37 } 38 for (i=tot;i>=0;i--) 39 if (f[i]<=m) 40 break; 41 printf("%d\n",i); 42 } 43 return 0; 44 } 45 /* 46 47 */