随便写个标题吧。。算不算标题党? 整理一下最近写的题目。
大连网络赛:
To Miss Our Children Time
背包问题,排个序就行了,题目描述不清。。
Find Metal Mineral
树形动归,f[x][j]表示以x为根的树,前i个子树放j个机器人不回来的最小值,DFS的感觉。f[x][0]表示放一个再出来。做的第一个树形动归,参照别人的代码,很巧妙的写法嘛。刚才看题目忘了具体怎么写了= =
void work(int x,int prev) { for (int i=head[x];i!=-1;i=edge[i].next) { if (edge[i].y==prev) continue; work(edge[i].y,x); for (int j=k;j>=0;j--) { f[x][j]+=f[edge[i].y][0]+edge[i].w*2; for (int l=0;l<j;l++) f[x][j]=min(f[x][j],f[x][l]+edge[i].w*(j-l)+f[edge[i].y][j-l]); } } }
PS:原来这个叫做分组背包= =
The Frog’s Games
比赛的时候以为是DP,结果就是个二分…
The kth great number
最简单的办法就是弄一个最小堆,堆顶就是答案,priority_queue用起来很爽。
priority_queue <int, vector<int>, greater<int> > heap; if (heap.size()<k) heap.push(temp); else if (temp>heap.top()) { heap.pop(); heap.push(temp); }
还可以写个treap..treap的删除还不会写= =
Dave
注意正方形的顶点不一定是题中的点。
把点分别按x和y排序,四条线扫描,写得比较乱= =
The 36th ACM/ICPC Asia Regional Shanghai Site —— Warmup
Working in Beijing
Parsing URL
两道水题,第一题题目说明不清楚= = 做做调节心情
上海网络赛
24 Puzzle
如果空位在角上则挪到中间的正方形里,然后比较8个角是否相同,相同才有可能有解。对于4*4,左右交换不改变逆序对,上下交换时逆序数的奇偶性改变一次(0-3,3-0,1-2,2-1)。
http://zhyu.me/acm/hdu-4021.html
觉得这个证明不完备,没想好怎么证。
Bombing
multiset真的很爽…
typedef map<int, multiset<int> > dict; void work(dict &a, dict &b, int &x) //delete a(x) from b { printf("%d\n",a[x].size()); for (multiset<int>::iterator iter=a[x].begin();iter!=a[x].end();iter++) { b[*iter].erase(x); } a[x].clear(); } int main() { int n,m,x,y; while (scanf("%d%d",&n,&m)!=EOF) { if (n==0 && m==0) break; dict a,b; for (int i=0;i<n;i++) { scanf("%d%d",&x,&y); a[x].insert(y); b[y].insert(x); } for (int i=0;i<m;i++) { scanf("%d%d",&x,&y); if (x==0) work(a,b,y); else work(b,a,y); } printf("\n"); } return 0; }
Game
比较简单的博弈问题,比赛的时候没静下心来想。
分组讨论,注意一个细节,9、10如果竖着的放好了,对方就不用抢这种了。
成都网络赛
Graph
给最短边求原图,原来可以这样写
void work(const int n) { for (int k=0;k<n;k++) for (int i=0;i<n;i++) for (int j=0;j<n;j++) { if (i==j || i==k || k==j) continue; if ((!visited[i][j]) && map[i][k]+map[k][j]==map[i][j]) { ++c; visited[i][j]=true; } } }
printf("%d\n",n*(n-1)-c);
Rolling Hongshu
物理题,考虑顶点和所有bitter potato。题目描述挺好玩…
The Social Network
第一次用map。
map<string,int> num;
读入:
cin>>s1>>s2; if (num.count(s1)) n1=num.find(s1)->second; else { num.insert(make_pair(s1, ++count)); n1=count; sn[n1]=s1; } if (num.count(s2)) n2=num.find(s2)->second; else { num.insert(make_pair(s2, ++count)); n2=count; sn[n2]=s2; } f[n1][++f[n1][0]]=n2;//f[n1]存n1的朋友们 f[n2][++f[n2][0]]=n1;
接下来就慢慢弄吧…
北京网络赛
Eliminate Witches!
模拟,递归处理,WA好几次= =
不过这个是我在今年网络赛时作出的第一道题= =
Panda
树状数组。a[i]表示以i开头的是不是wbw。自己没想到这种方法。
if (s[i]=='w' && s[i+1]=='b' && s[i+2]=='w') add(i,1);
Tourism Planning
第一个状态压缩DP,把某人去不去用二进制表示。
f[15][1030];//f[i][j]前i个景点,第j个状态的最大值
预处理当前状态能由哪些状态得到,如果不预处理HDU可以很快AC,BOJ会TLE= =
wolf5x
概率DP。
比赛时就想对了方法,读题不认真,以为第一步左右概率相同呢。
赛后写好,发现还是看错题了,以为是求停止位置,原来是求步数的期望,可以直接把所有状态的概率加起来!
int main() { int t; int n,a,b; int i,j; double ans; double p[2010][4]; double f[2010][4]; double temp1,temp2,temp3; scanf("%d",&t); while (t--) { scanf("%d%d%d",&n,&a,&b); ans=0; for (i=1;i<=n;i++) scanf("%lf%lf%lf%lf",&p[i][0],&p[i][1],&p[i][2],&p[i][3]); memset(f,0,sizeof(f)); temp1=1; for (i=a;i<=b;i++) { if (i>n) { ans+=temp1; break; } for (j=1;j<=3;j++) f[i][j]=temp1*p[i][j]; temp1*=p[i][0]; } for (i=a;i<=n;i++) { temp1=temp2=temp3=1; for (j=i+a;j<=i+b;j++) { if (j>n) { ans+=f[i][1]*temp1+f[i][2]*temp2+f[i][3]*temp3; break; } else { f[j][1]+=(f[i][2]*temp2+f[i][3]*temp3)*p[j][1]; //表示以这种状态踩在j f[j][2]+=(f[i][1]*temp1+f[i][3]*temp3)*p[j][2]; f[j][3]+=(f[i][1]*temp1+f[i][2]*temp2+f[i][3]*temp3)*p[j][3]; temp1*=p[j][0]+p[j][1]; //tempi表示f[prev][i]不能走的概率 temp2*=p[j][0]+p[j][2]; temp3*=p[j][0]; } } ans+=f[i][1]+f[i][2]+f[i][3]; } printf("%.8lf\n",ans); } return 0; }
大连现场赛
The Last Puzzle
对于任意一段,都是从任意一端开始到中间,因为如果从中间开始,还是要先到两端再到最终节点。想通了这个就很好写了。
f[i][j][k]表示从i到j这一段,k表示从左或从右开始,所需的最短时间。不可能则记为-1。
Hexadecimal View
水题,不知道可以用 %x 输出…
Number String
f[i][j]存当前所有可能情况,即i=n时只有f[n][1]。表示字符串中第i位是,表中第j个有几种情况。f[i+1]保存的数量比f[i]少一个,因为有一个数字被选走了。
for (i=1;i<=n;i++) f[1][i]=1; for (int ii=0;ii<n;ii++) { i=ii+2; if (str[ii]=='I') { f[i][1]=f[i-1][1]; for (j=2;j<=n-i+1;j++) f[i][j]=(f[i-1][j]+f[i][j-1])%MOD; } else if (str[ii]=='D') { f[i][n-i+1]=f[i-1][n-i+2]; for (j=n-i;j>=1;j--) f[i][j]=(f[i-1][j+1]+f[i][j+1])%MOD; } else { sum=0; for (j=1;j<=n-i+2;j++) sum=(sum+f[i-1][j])%MOD; for (j=1;j<=n-i+1;j++) f[i][j]=sum; } } printf("%d\n",f[n][1]);
福州网络赛
SanguoSHA
当时不爽,写这题写了好久= = 最后写好了觉得会WA,于是没交,回宿舍交了发现过了。
STL里居然有全排列… next_permutation 和 prev_permutation。
===
仔细想想有些题还是可以做的,并不是不会算法,而是想不到。另外数学太烂了。
大二,作业没大一多了,更加觉得时间不够用。平时训练做题效率很低。还有好多想学的东西呢。