Client/Server UDP通信-java

Client端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.net.*;  
import java.io.*;
public class UDPClient{
public static void main(String args[]){
DatagramSocket socket = null;
DatagramPacket packet = null;
InetAddress address = null;
String s = "send the data , please !";
byte buf[] = new byte[256];
buf = s.getBytes();
byte ip[] = {(byte)127,(byte)0,(byte)0,(byte)1};
try{
address = InetAddress.getByAddress(ip);
socket = new DatagramSocket();
packet = new DatagramPacket(buf,buf.length,address,1080);
socket.send(packet);
Thread.sleep(2000);
packet = new DatagramPacket(buf,buf.length);
socket.receive(packet);
s = new String(packet.getData());
System.out.println("received data is :"+s);
}catch(Exception e){
System.out.println(e.toString());
}
socket.close();
}
}

Server端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.net.*;  
import java.io.*;
import java.util.*;
public class UDPSever{
public static void main(String args[]){
DatagramSocket socket1=null;
DatagramPacket packet1=null;
String s1;
byte buf1[]= new byte[256];
InetAddress address1 = null;
int port1;
Date date1;
try{
socket1 = new DatagramSocket(1080);
packet1 = new DatagramPacket(buf1,buf1.length);
socket1.receive(packet1);
s1=new String(packet1.getData());
System.out.println("received request:"+s1);
port1 = packet1.getPort();
address1= packet1.getAddress();
date1 = new Date();
s1 = date1.toString();
buf1= s1.getBytes();
packet1= new DatagramPacket(buf1,buf1.length,address1,port1);
socket1.send(packet1);
Thread.sleep(2000);
}catch(Exception e){
System.out.println(e.toString());
}
socket1.close();
}
}

如果把这IP地址改改。就可以做简单的网络通信。
网络编程刚接触,慢慢学习。

nyoj253 LK的旅行(旋转卡壳法)

做这个题之前最好先做下78圈水池这题,这两个题差不多,区别在于一个是求哪些点在凸包内,这个是求凸包的两个最远的点的距离的平方。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include<stdio.h>  
#include<math.h>
#include<stdlib.h>
#define NN 100005
#define max(a,b) ((a)>(b)?(a):(b))
const int INF=1<<30;
typedef struct Point{
int x,y;
}P;
P a[NN],q[NN];
int top;
int dis_2(P p1,P p2)
{
return (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y);
}
int xx(P p,P p1,P p2)
{
return (p1.x-p.x)*(p2.y-p.y)-(p1.y-p.y)*(p2.x-p.x);
}
int comp(const void *x,const void *y)
{
P i=*(P *)x;
P j=*(P *)y;
if(i.x!=j.x)
return i.x-j.x;
else
return i.y-j.y;
}
int main()
{
int N,i,n;
scanf("%d",&N);
while(N--)
{
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
}
qsort(a,n,sizeof(a[0]),comp);

top=0;
q[0]=a[0];
for(i=1;i<n;i++)//下凸包
{
if(a[i].x==q[top].x && a[i].y==q[top].y) continue;
while(top>=1 && xx(q[top-1],q[top],a[i])>=0) top--;
q[++top]=a[i];
}
int t=top;
for(i=n-1;i>=0;i--)//上凸包
{
if(a[i].x==q[top].x && a[i].y==q[top].y) continue;
while(top>t && xx(q[top-1],q[top],a[i])>=0) top--;
q[++top]=a[i];
}
double ans=0.0;
t=1;
for(i=0;i<top;i++)
{
while(xx(q[i+1],q[t],q[i]) > xx(q[i+1],q[t+1],q[i])) t=(t+1)%top;
ans=max(ans,max(dis_2(q[i],q[t]),dis_2(q[i+1],q[t+1])));
}
printf("%.0lf\n",ans);
}
return 0;
}

nyoj42 一笔画问题(欧拉图)

这题其实说不上难度4,只是一个简单的欧拉图判断,给一些点,首先判断连通性。如果不连通,就谈不上是欧拉图。
如果是连通的,在判断度的数目,每个顶点都是偶数个或者只有两个是奇数个。这样就可以构成欧拉图。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include<stdio.h>  
#include<string.h>
#include<vector>
using namespace std;
vector <int > v[1005];
int cnt;
bool vis[1005];
void dfs(int k)
{
int i;
for(i=0;i<v[k].size();i++)
{
int t=v[k][i];
if(!vis[t])
{
vis[t]=true;
cnt++;
dfs(t);
}
}
}
int main()
{
int N,n,m,a,b,i;
scanf("%d",&N);
while(N--)
{
memset(vis,false,sizeof(vis));
scanf("%d%d",&n,&m);
while(m--)
{
scanf("%d%d",&a,&b);
v[a].push_back(b);
v[b].push_back(a);
}
vis[b]=true;
cnt=1;
dfs(b);
int count=0;
if(cnt==n)
{
for(i=1;i<=n;i++)
{

if(v[i].size()&1) count++;
v[i].clear();
}
}
printf("%s\n",(count==0 || count==2) && cnt==n?"Yes":"No");
}
return 0;
}

nyoj78 圈水池(凸包问题)

解决这样的问题两个出名的算法:

  • Graham扫描法,运行时间为O(nlgn)
  • Jarvis步进法,运行时间为O(nh),h为凸包中的顶点数

Graham扫描法
基本思想:通过设置一个关于候选点的堆栈s来解决凸包问题。
操作:输入集合Q中的每一个点都被压入栈一次,非CH(Q)(表示Q的凸包)中的顶点的点最终将被弹出堆栈,当算法终止时,堆栈S中仅包含CH(Q)中的顶点,其顺序为个各顶点在边界上出现的逆时针方向排列的顺序。
注:下列过程要求|Q|>=3,它调用函数TOP(S)返回处于堆栈S 顶部的点,并调用函数NEXT-TO –TOP(S)返回处于堆栈顶部下面的那个点。但不改变堆栈的结构。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include<stdio.h>  
#include<stdlib.h>
#include<limits.h>
#include<math.h>
#include<iostream>
using namespace std;
typedef struct Point
{
int x,y;
}P;
int q[105];//zhan
P a[105],b[105];
int top;
void _swap(int u,int uu)
{
P t=a[u];
a[u]=a[uu];
a[uu]=t;
}
double dis(P p1,P p2)
{
return sqrt(pow(fabs((double)p1.x-p2.x),2)+pow(fabs((double)p1.y-p2.y),2));
}
int xchen(P p,P p1,P p2)//左转关系判定。大于0就是。
{
return (p1.x-p.x)*(p2.y-p.y)-(p1.y-p.y)*(p2.x-p.x);
}
int comp(const void *x,const void *y)
{
int t=xchen(a[0],*(P *)x,*(P *)y);//以极角排序。
if(t==0)
return dis(*(P *)x,a[0])-dis(*(P *)y,a[0])>0?1:-1;//如果极角相等,就按照和基本点的距离排序。
else
return t;
}
int _comp(const void *c,const void *d)
{
P x=*(P *)c;
P y=*(P *)d;
if(x.x!=y.x)
return x.x-y.x;
else
return x.y-y.y;
}
int main()
{
int N,i,n,j;
scanf("%d",&N);
while(N--)
{
scanf("%d",&n);
int tt=INT_MAX;
int loc=0;
for(i=0;i<n;i++)
{
cin>>a[i].x>>a[i].y;
if(a[i].y<tt || (a[i].y==tt && a[i].x<=a[loc].x)){ tt=a[i].y; loc=i; }//求最小的y点的坐标。
}
_swap(0,loc);//交换到第一个。
qsort(a+1,n-1,sizeof(a[0]),comp);//第一个基本点不参与排序。
// for(i=0;i<n;i++)
// cout<<a[i].x<<"..."<<a[i].y<<endl;
top=1;
q[0]=0;q[1]=1;
for(i=2;i<n;i++)
{
while(top>=1 && xchen(a[q[top-1]],a[q[top]],a[i])>0) top--;//这里xchen是求叉乘。>0是包括在一条直线上的点。
q[++top]=i;
}
for(i=0,j=0;i<=top;i++,j++)
b[j]=a[q[i]];
qsort(b,top+1,sizeof(b[0]),_comp);
for(i=0;i<=top;i++)
cout<<b[i].x<<" "<<b[i].y<<endl;
}
return 0;
}

nyoj239 月老的难题

这题我是研究了好久,就是去理解那个增广路花了一大部分时间。
有很多都是伪代码写的,说了个大致思想,但是没个试题给具体点的代码,所以我很困惑。
然后今天模仿一下别人做的题,对着题和代码认真想一遍。仔细想了那个神秘的增广路。
慢慢的明白了,哈哈。
然后我就小试牛刀一下,做了这题。
开始我代码就写对了,有个地方,就是一个小错误,让我改半天,wa了三四次。

1
2
3
for(i=0;i<=n;i++)
v[i].clear();
printf("%d\n",match);

清空应该是i<=n的,我开始一直写成了i<n;就因为这,一直错。
后来我还认认真真的把别人代码抄了一遍,结果对了,我郁闷啊。

通过了后我就研究了标准代码,和我开始写的一样,就是初始化直接是memset初始化的。

在经过我的再三思之后,终于发现了这个错误。
哎。我还以为。。。。。。啥都不说了。
下次再犯错误就。。。。。下面是ac代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include<stdio.h>  
#include<string.h>
#include<vector>
using namespace std;
#define MAX 502
int mat[MAX];
bool used[MAX];
vector<int > v[MAX];
int n;
bool crosspath(int k)
{
int i;
for(i=0;i<v[k].size();i++)
{
int t=v[k][i];
if(!used[t])
{
used[t]=true;
if(mat[t]==0|| crosspath(mat[t]))
{
mat[t]=k;
return true;
}
}
}
return false;
}
int main()
{
int N;
int a,b,k,i;
scanf("%d",&N);
while(N--)
{
scanf("%d%d",&n,&k);
for(i=0;i<k;i++)
{
scanf("%d%d",&a,&b);
v[a].push_back(b);//我看见别人都是把这改了,b改成n+b;我开始也学着他们改,但是后来我发现改了没用,根本没影响。
}
int match=0;
memset(mat,0,sizeof(mat));
for(i=1;i<=n;i++)
{
memset(used,false,sizeof(used));
if(crosspath(i))
match++;
}
for(i=0;i<=n;i++)
v[i].clear();
printf("%d\n",match);
}
return 0;
}