昨日练习赛,很简单,但做的并不好
T1:暴力枚举100个其余等效状态O(1)加入答案,虽然正解好像是容斥原理
1 n=rd(),m=rd(); 2 if(n<3 || m<3) {cout<<0;return 0;} 3 FOR(i,3,n) cc[i]=(i-2)*(m-2); 4 //FOR(i,1,n) cout<<cc[i]<<" ";cout<<endl; 5 FOR(i,1,n-2) 6 { 7 ll ansn=0; 8 FOR(j,1,m-2) 9 { 10 ll ansnn=0; 11 ansnn+=cc[i-1]+cc[n-i-2]; 12 ansnn+=(max(j-3,lng)+max(m-j-4,lng))*((i>=3)+(i>=2)+1)+(max(j-2,lng)+max(m-j-3,lng))*((i<=n-3)+(i<=n-4)); 13 ansn+=ansnn; 14 if(m>=10 && j==4) {ansn+=(m-9)*ansnn;j=m-5;} 15 } 16 ans+=ansn; 17 if(n>=10 && i==4) {ans+=(n-9)*ansn;i=n-5;} 18 } 19 cout<<ans;
结果最后画蛇添足改错了
T2:DP转移 结果被数学期望吓蒙了
光看时间复杂度,50 分是可以拿满分的,但是存在一个严峻问题:如果是随机数据,数据生成后单个概率大约在 0.3 ∼ 0.4 ,而 0.4300 精度早就在能承受的范围后面好远了。
所以就提出一种解决方案,把所有的概率取个对数,底数随便定(自带log()函数即可),把乘法改成加法即可。
1 scanf("%d%d%d",&n,&m,&k); 2 FOR(i,1,k) FOR(j,1,n) f[i][j]=-(1<<30); 3 FOR(i,1,n) FOR(j,1,n) scanf("%lf",&a[i][j]),a[i][j]=log(a[i][j]); 4 FOR(i,1,n) FOR(j,1,m) scanf("%lf",&b[i][j]),b[i][j]=log(b[i][j]); 5 FOR(i,1,n) scanf("%lf",&f[1][i]),f[1][i]=log(f[1][i]); 6 FOR(i,1,k) scanf("%d",&hd[i]); 7 FOR(i,1,n) f[1][i]+=b[i][hd[1]]; 8 FOR(i,2,k) FOR(j,1,n) FOR(kk,1,n) 9 { 10 double tp=f[i-1][kk]+a[kk][j]+b[j][hd[i]]; 11 if(f[i][j]<tp) 12 { 13 f[i][j]=tp; 14 pre[i][j]=kk; 15 } 16 } 17 int ss=1; 18 FOR(i,2,n) if(f[k][i]>f[k][ss]) ss=i; 19 For(i,k,1) {ans[i]=ss;ss=pre[i][ss];} 20 FOR(i,1,k) printf("%d ",ans[i]);
模拟退火:
对x,y分别random_shuffle得到初始值,把不合法的点压入队列,每次取出队头元素,随机取限制范围内值。
A.未冲突,接受
B.与之前的点冲突,一定概率接受。若接受,则把造成的不合法的点压入栈。
期望80分
T3
贪心. 考虑一个更简单的问题:
给一个长为 N 的序列,有 N 个车,每个车可以放入区间 [l,r] 的任意一个位置,每个位置最多可以放 1 个车。
将每个车按 l 为第一关键字,r 为第二关键字排序。从左向右扫描整个序,每扫到一个位置,将能放在该位置上的,当前还未放置的所有车中 r 最小的那个放在该位置。每个位置确定车是 O(n) 的,总复杂度 O(n2) 。
回归到 2 维, 注意到每一维是独立的,即确定了所有车第一维的位置, 第二维不受影响. 故每一维单独做即可。
在 80 分基础上,用堆维护当前未放置的所有车中 r 最小的车. 每个位置,确定车是 O(logn) 的, 总复杂度 O(nlogn) 。
1 //参考过jxl_orz的程序 2 const int N=100010; 3 struct car{int u,d,l,r;}a[N]; 4 struct node 5 { 6 int cc,id; 7 node(int CC,int ID){cc=CC;id=ID;} 8 bool operator < (const node a)const {return cc==a.cc?id>a.id:cc>a.cc;} 9 }; 10 int x[N],y[N]; 11 int n; 12 priority_queue<node> s1,s2; 13 vector<int> ss1[N],ss2[N]; 14 15 void solx() 16 { 17 FOR(i,1,n) ss1[a[i].u].push_back(i); 18 FOR(i,1,n) 19 { 20 int hhh=ss1[i].size()-1; 21 //cerr<<i<<" "<<hhh<<endl; 22 FOR(j,0,hhh) s1.push((node){a[ss1[i][j]].d,ss1[i][j]});//cerr<<ss1[i][j]<<" ", 23 //cerr<<endl<<s1.top().cc<<" "<<s1.top().id<<endl; 24 x[s1.top().id]=i;s1.pop(); 25 } 26 } 27 28 void soly() 29 { 30 FOR(i,1,n) ss2[a[i].l].push_back(i); 31 FOR(i,1,n) 32 { 33 int hhh=ss2[i].size()-1; 34 FOR(j,0,hhh) s2.push(node(a[ss2[i][j]].r,ss2[i][j])); 35 y[s2.top().id]=i;s2.pop(); 36 } 37 } 38 39 int main() 40 { 41 freopen("chessboard.in","r",stdin); 42 freopen("chessboard.out","w",stdout); 43 n=rd(); 44 if(n==1) {cout<<"1 1";return 0;} 45 FOR(i,1,n) a[i].u=rd(),a[i].d=rd(),a[i].l=rd(),a[i].r=rd(); 46 //FOR(i,1,n) cout<<a[i].u<<" "<<a[i].d<<" "<<a[i].l<<" "<<a[i].r<<endl; 47 solx();soly(); 48 FOR(i,1,n) printf("%d %d ",x[i],y[i]); 49 return 0; 50 }