一会儿物理实验考试选课~貌似网站又瘫痪了。。。
昨天网上稍微看了看博弈,然后今天上午做了一点博弈。。SG函数完全是套模版。。再难一点的博弈就不会了。。
仍然停留在找规律的弱菜水平。。。另外看了一点欧拉回路 。。。原来这东西一般会用到并查集。。(一阵窃喜。。),欧拉图的判定条件还没有搞会。。。
下午和晚上再看看,然后打一下的内容差不多快结束了吧。。
然后就开始复习unix...下周考试了撒。。。
9. 博弈论
a) 博弈问题与SG函数的定义
b) 多个博弈问题SG值的合并
10. 图论:
a) 图的邻接矩阵与邻接表两种常见存储方式
b) 欧拉路的判定
c) 单最短路bellman-ford算法dijkstra算法。
d) 最小生成树的kruskal算法与prim算法。
11. 学会使用C语言进行网络编程与多线程编程
12. 高等数学
13. 线性代数
a) 明确线性代数的重要性,首先是课本必须学好
b) 编写一个Matrix类,进行矩阵的各种操作,并求编写程序解线性方程组。
c) 推荐做一两道“矩阵运算”分类下的题目。
题解:
hdu 1846:http://acm.hdu.edu.cn/showproblem.php?pid=1846
/*
额。。还有比这更简单的博弈么。。。
*/
#include<iostream>
using namespace std;
int main()
{
int T;
cin>>T;
while(T--)
{
int n,m;
cin>>n>>m;
if(n%(m+1)==0)
{
cout<<"second"<<endl;
}
else
{
cout<<"first"<<endl;
}
}
system("pause");
return 0;
}
hdu 1847: http://acm.hdu.edu.cn/showproblem.php?pid=1847
/*
变种bash博弈
请允许我采用枚举法找规律。
*/
#include<iostream>
using namespace std;
int main()
{
int n;
while(cin>>n)
{
if(n%3==0)
cout<<"Cici"<<endl;
else
cout<<"Kiki"<<endl;
}
system("pause");
return 0;
}
hdu 1907: http://acm.hdu.edu.cn/showproblem.php?pid=1907
/*
Nim博弈裸题。。
什么充裕态孤单态。。目前还没看懂。。
纯粹套的模版。。
*/
#include<iostream>
using namespace std;
int main()
{
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
int num=0;
int ans=0;
while(n--)
{
int a;
cin>>a;
if(a>1)
{
num++;
}
ans^=a;
}
if(num)
{
if(ans==0)
{
cout<<"Brother"<<endl;
}
else
{
cout<<"John"<<endl;
}
}
else
{
if(ans==0)
{
cout<<"John"<<endl;
}
else
{
cout<<"Brother"<<endl;
}
}
}
system("pause");
return 0;
}
hdu 2509: http://acm.hdu.edu.cn/showproblem.php?pid=2509
/*
Nim博弈裸题。。
什么充裕态孤单态。。目前还没看懂。。
纯粹套的模版。。
*/
#include<iostream>
using namespace std;
int main()
{
int T;
int n;
while(cin>>n)
{
int num=0;
int ans=0;
while(n--)
{
int a;
cin>>a;
if(a>1)
{
num++;
}
ans^=a;
}
if(num)
{
if(ans==0)
{
cout<<"No"<<endl;
}
else
{
cout<<"Yes"<<endl;
}
}
else
{
if(ans==0)
{
cout<<"Yes"<<endl;
}
else
{
cout<<"No"<<endl;
}
}
}
system("pause");
return 0;
}
hdu 1517: http://acm.hdu.edu.cn/showproblem.php?pid=1517
/*
感觉和bash博弈差不多,只不过由加法变成了乘法,
木有想到。。。
题解来自:http://qianmacao.blog.163.com/blog/static/203397180201223174133470/
犀利啊。。
①、如果输入是2~9,因为Stan是先手,所以Stan必胜。
②、如果输入是10~18(9*2),因为Ollie是后手,不管第一次Stan乘的是多少,Stan肯定在2~9之间,如果Stan乘以2,那么Ollie就乘以9,那么Ollie乘以大于1的数都能超过10~18中的任何一个数,Ollie必胜。
③、如果输入的是19~162(9*2*9),那么这个范围Stan必胜。
④、如果输入是163~324(2*9*2*9),这个是Ollie的必胜范围。
…………
可以发现必胜态是对称的。
如果“我方”首先给出了一个在N不断除18后的得到不足18的数M,“我方”就可以胜利,然而双方都很聪明,所以这样胜负就决定与N了,如果N不断除18后的得到不足18的数M,如果1<M<=9则先手胜利,即Stan wins.如果9<M<=18则后手胜利。
*/
#include <iostream>
using namespace std;
int main()
{
double n;
while(cin >> n)
{
while(n > 18)
n /= 18;
if(n <= 9)
cout << "Stan wins." << endl;
else
cout << "Ollie wins." << endl;
}
return 0;
}
hdu 1536: http://acm.hdu.edu.cn/showproblem.php?pid=1536
/*
裸SG函数
套模版。。。
*/
#include <iostream>
#include <algorithm>
using namespace std;
const int M = 10005;
int sg[M];
int set[M];
int check[M];
int k,n,m;
int mmax;
int mex(int v)
{
if(sg[v] != -1)
return sg[v];
bool vis[101] = {0};
for(int i = 0; i < k; i++)
{
if(v-set[i] < 0)
break;
sg[v-set[i]] = mex(v-set[i]);
vis[sg[v-set[i]]] = true;
}
for(int i = 0; ; i++)
if(!vis[i])
{
sg[v] = i;
break;
}
return sg[v];
}
int main()
{
while(cin>>k&&k!=0)
{
mmax = 0;
memset(set,0,sizeof(set));
for(int j = 0; j < k; j++)
{
cin>>set[j];
}
sort(set,set+k);
memset(sg,-1,sizeof(sg));
sg[0] = 0;
cin>>m;
while(m--)
{
cin>>n;
int ans = 0;
for(int i = 0; i < n; i++)
{
int x;
cin>>x;
if(sg[x] == -1)
sg[x] = mex(x);
ans ^= sg[x];
}
if(!ans)
cout<<"L";
else
cout<<"W";
}
cout<<endl;
}
return 0;
}
hdu 1878: http://acm.hdu.edu.cn/showproblem.php?pid=1878
/*
欧拉回路判定
1.回路(用并查集判断(擅长啊哈哈))
2.欧拉图(不含奇数度结点)
*/
#include<iostream>
using namespace std;
int father[1005];
int map[1005];
int num;
int find(int x)
{
if(x==father[x])
{
return x;
}
else
{
return find(father[x]);
}
}
void Union(int x,int y)
{
x=find(x);
y=find(y);
if(x!=y)
{
father[x]=y;
num++;
}
}
void init()
{
for(int i=1;i<=1000;i++)
{
father[i]=i;
}
}
int main()
{
int n,m;
while(cin>>n&&n!=0)
{
init();
memset(map,0,sizeof(map));
num=1;
cin>>m;
while(m--)
{
int x,y;
cin>>x>>y;
map[x]++;
map[y]++;
Union(x,y);
}
if(num==n)
{
int i;
for(i=1;i<=n;i++)
{
if(map[i]%2==1)
{
cout<<"0"<<endl;
break;
}
}
if(i>n)
{
cout<<"1"<<endl;
}
}
else
{
cout<<"0"<<endl;
}
}
system("pause");
return 0;
}
hdu 3018: http://acm.hdu.edu.cn/showproblem.php?pid=3018
/*
欧拉回路+并查集
一笔画问题
数组开小了wa了好几次
这个题其实就个一笔划问题,如果是个欧拉回路一笔就可以完成,如果是个其它连通集,
要根据这个集合的奇度数而定,笔划数=奇度数/2,用并查集来判断有多少个连通集,
通过判断度数是奇偶性来确定是否为欧拉回路;总之笔划数 = 奇度数%2 + 欧拉回路数;
*/
#include<iostream>
using namespace std;
int n,m;
int father[200005];
int map[200005];
int cnt[200005];
int a[200005];
int b[200005];
int find(int x)
{
if(x==father[x])
{
return x;
}
else
{
return find(father[x]);
}
}
void Union(int x,int y)
{
x=find(x);
y=find(y);
if(x!=y)
{
father[x]=y;
cnt[y]+=cnt[x];
}
}
void init()
{
memset(map,0,sizeof(map));
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=n;i++)
{
father[i]=i;
}
}
int main()
{
while(cin>>n>>m)
{
init();
for(int i=1;i<=m;i++)
{
cin>>a[i]>>b[i];
map[a[i]]++;
map[b[i]]++;
}
for(int i=1;i<=n;i++)
{
if(map[i]%2==1)
{
cnt[i]=1;
}
}
for(int i=1;i<=m;i++)
{
Union(a[i],b[i]);
}
int sum=0;
for(int i=1;i<=n;i++)
{
if(map[i]&&father[i]==i)
{
if(cnt[i]==0)
{
sum++;
}
else
{
sum+=cnt[i]/2;
}
}
}
cout<<sum<<endl;
}
system("pause");
return 0;
}
hdu 1116: http://acm.hdu.edu.cn/showproblem.php?pid=1116
/*
再好好看看欧拉图。。。
知道用并查集但不知道要干嘛。。。
搜的题解:
思路:并查集&&欧拉通路
1)所有的点联通
2)欧拉回路中所有点的入度和出度一样。
3)欧拉通路中起点的入度 - 出度 = 1,终点的 初度 - 入度 = 1,
其他的所有点入度 = 出度;
*/
#include <iostream>
using namespace std;
#define M 30
int father[M],vis[M],in[M],out[M],ans[M];
char ch[1005];
int find(int x)
{
if(x==father[x])
{
return x;
}
else
{
return find(father[x]);
}
}
void Union(int x,int y)
{
x=find(x);
y=find(y);
if(x!=y)
{
father[x]=y;
}
}
void init()
{
memset(vis,0,sizeof(vis));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
for(int i=0;i<26;i++)
father[i]=i;
}
int main()
{
int T,n,a,b;
cin>>T;
while(T--)
{
cin>>n;
init();
for(int i=0;i<n;i++)
{
cin>>ch;
a=ch[0]-'a';
b=ch[strlen(ch)-1]-'a';
Union(a,b);
out[a]++;
in[b]++;
vis[a]=1;
vis[b]=1;
}
for(int i=0;i<26;i++)
father[i]=find(i);
int cnt=0;
for(int i=0;i<26;i++)
if(vis[i]&&father[i]==i)
cnt++;
if(cnt>1)
{
cout<<"The door cannot be opened."<<endl;
continue;
}
int j=0;
for(int i=0;i<26;i++)
if(vis[i]&&out[i]!=in[i])
ans[j++]=i;
if(j==0)
{
cout<<"Ordering is possible."<<endl;
continue;
}
if(j==2&&( (out[ans[0]]-in[ans[0]]==1&&in[ans[j-1]]-out[ans[j-1]]==1)
||(out[ans[j-1]]-in[ans[j-1]]==1&&in[ans[0]]-out[ans[0]]==1) ))
{
cout<<"Ordering is possible."<<endl;
continue;
}
cout<<"The door cannot be opened."<<endl;
}
}
旁边这人可真烦尼玛。。。抖腿鼻涕一时爽。。