「杂谈·一」浅谈打表

1. 打表之“是什么”“为什么”“怎么办”

1-1. 打表是什么?

打表,顾名思义,就是将所有可能的答案打成一个表,进行看似不太正经地求解。


1-2. 为什么要打表?

有时,题目输入的数据很小,我们无法用程序高效求出,这时,我们就可以预先算出答案,存储进一个数组中,然后就可以“对号入座”了。


1-3. 怎么打表?

一般地,我们会有一个 table.cpp/py(用来打表的程序)与 solve.cpp(最终程序),先执行 table.cpp,一般会输出到文件 table.txt,然后复制 table.txt 的内容到 solve.cpp 轻松解题。



2. 打表题选——直接打表

这些题目,我们直接打表输出即可。

2-1. 蛇形方阵

题目描述

给出一个不大于 9 9 9 的正整数 n n n,输出 n × n n\times n n×n 的蛇形方阵。
从左上角填上 1 1 1 开始,顺时针方向依次填入数字,如同样例所示。注意每个数字有都会占用 3 3 3 个字符,前面使用空格齐。

输入格式

输入一个正整数 n n n,含义如题所述。

输出格式

输出符合题目要求的蛇形矩阵。

样例输入

4

样例输出

  1  2  3  4
 12 13 14  5
 11 16 15  6
 10  9  8  7

提示

数据保证, 1 ≤ n ≤ 9 1 \leq n \leq 9 1n9

记得在学数组时,我们会写出类似这样的程序:

#include<bits/stdc++.h>
using namespace std;

int n,t,i,j,a[105][105];

int main()
{
	cin>>n;
	t=i=j=1;
	while(t<=n*n)
	{
		while(j<=n&&!a[i][j]){a[i][j]=t++;j++;}i++;j--;
		while(i<=n&&!a[i][j]){a[i][j]=t++;i++;}i--;j--;
		while(j>=1&&!a[i][j]){a[i][j]=t++;j--;}i--;j++;
		while(i>=1&&!a[i][j]){a[i][j]=t++;i--;}i++;j++;
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cout<<setw(3)<<a[i][j];
		}
		cout<<endl;
	}
	return 0;
}

假如有一天,你颓废了,不会写了(雾)。
此时,你发现:

数据保证, 1 ≤ n ≤ 9 1 \leq n \leq 9 1n9

于是,我们可以打表了。
AC Code:

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int n;
	cin>>n;
	if(n==1) puts("  1");
	if(n==2) puts("  1  2\n  4  3");
	if(n==3) puts("  1  2  3\n  8  9  4\n  7  6  5");
	if(n==4) puts("  1  2  3  4\n 12 13 14  5\n 11 15 16  6\n 10  9  8  7");
	if(n==5) puts("  1  2  3  4  5\n 16 17 18 19  6\n 15 24 25 20  7\n 14 23 22 21  8\n 13 12 11 10  9");
	if(n==6) puts("  1  2  3  4  5  6\n 20 21 22 23 24  7\n 19 32 33 34 25  8\n 18 31 36 35 26  9\n 17 30 29 28 27 10\n 16 15 14 13 12 11");
	if(n==7) puts("  1  2  3  4  5  6  7\n 24 25 26 27 28 29  8\n 23 40 41 42 43 30  9\n 22 39 48 49 44 31 10\n 21 38 47 46 45 32 11\n 20 37 36 35 34 33 12\n 19 18 17 16 15 14 13");
	if(n==8) puts("  1  2  3  4  5  6  7  8\n 28 29 30 31 32 33 34  9\n 27 48 49 50 51 52 35 10\n 26 47 60 61 62 53 36 11\n 25 46 59 64 63 54 37 12\n 24 45 58 57 56 55 38 13\n 23 44 43 42 41 40 39 14\n 22 21 20 19 18 17 16 15");
	if(n==9) puts("  1  2  3  4  5  6  7  8  9\n 32 33 34 35 36 37 38 39 10\n 31 56 57 58 59 60 61 40 11\n 30 55 72 73 74 75 62 41 12\n 29 54 71 80 81 76 63 42 13\n 28 53 70 79 78 77 64 43 14\n 27 52 69 68 67 66 65 44 15\n 26 51 50 49 48 47 46 45 16\n 25 24 23 22 21 20 19 18 17");
	return 0;
}

2-2. T 型骨牌

题目描述

n × m n×m n×m 的棋盘上,摆入 T 型,T 型可以旋转,具体包括如下四个样式(# 代表被 T 型占据的格子,. 代表自由的格子):

###      ..#      .#.      #..
.#.      ###      .#.      ###
.#.      ..#      ###      #..

问最多能在 n × m n×m n×m 的棋盘上摆入多少个不重叠的T型。

输入格式

两个数 n , m ( 1 ≤ n , m ≤ 9 ) n,m(1\le n,m\le 9) n,m(1n,m9)

输出格式

一个数,最多能放入多少个 T 型。

样例输入

5 6

样例输出

4

提示

样例说明:

会发现,我们直接写这题,可以得到 70 pts 70\text{pts} 70pts 的好成绩。可惜你颓废了,不会优化(雾)。
此时,你又发现:

两个数 n , m ( 1 ≤ n , m ≤ 9 ) n,m(1\le n,m\le 9) n,m(1n,m9)

于是,我们又可以打表了。
AC Code:

#include<bits/stdc++.h>
using namespace std;
int ans[10][10];
int main()
{
	ans[3][3]=1;
	ans[3][4]=1;
	ans[3][5]=2;
	ans[3][6]=2;
	ans[3][7]=3;
	ans[3][8]=3;
	ans[3][9]=4;
	ans[4][3]=1;
	ans[4][4]=2;
	ans[4][5]=2;
	ans[4][6]=3;
	ans[4][7]=4;
	ans[4][8]=4;
	ans[4][9]=5;
	ans[5][3]=2;
	ans[5][4]=2;
	ans[5][5]=4;
	ans[5][6]=4;
	ans[5][7]=5;
	ans[5][8]=6;
	ans[5][9]=7;
	ans[6][3]=2;
	ans[6][4]=3;
	ans[6][5]=4;
	ans[6][6]=5;
	ans[6][7]=6;
	ans[6][8]=7;
	ans[6][9]=8;
	ans[7][3]=3;
	ans[7][4]=4;
	ans[7][5]=5;
	ans[7][6]=6;
	ans[7][7]=8;
	ans[7][8]=9;
	ans[7][9]=10;
	ans[8][3]=3;
	ans[8][4]=4;
	ans[8][5]=6;
	ans[8][6]=7;
	ans[8][7]=9;
	ans[8][8]=10;
	ans[8][9]=12;
	ans[9][3]=4;
	ans[9][4]=5;
	ans[9][5]=7;
	ans[9][6]=8;
	ans[9][7]=10;
	ans[9][8]=12;
	ans[9][9]=13;
	int n,m;
	cin>>n>>m;
	cout<<ans[n][m];
	return 0;
}

2-3. 球的体积

题目描述

已知一个半径为 r r r 的球体,现在问这个球的体积为多少?
计算时,取 π = 3.14 \pi = 3.14 π=3.14

输入格式

输入共一行,其中包括一个正整数 r r r 表示球体的半径。

输出格式

输出共一行,其中包括球体的体积。要求保留小数点后 5 5 5

样例输入

5

样例输出

523.33333

提示

1 ≤ r ≤ 100 1\leq r\leq 100 1r100

假如你不会处理保留小数点(雾)。


2-4. 旋转数塔

题目描述

X \text X X C \text C C 城著名的考古学家。一日,他被重金聘请调查一座荒漠中的宫殿。
宫殿大门紧闭,但这难不倒聪明的小 X \text X X 。他在隐蔽处发现了两个数字正方形:

X \text X X 略加思索便发现了其中的奥妙:把数字从小到大依次填入正方形中,每次填最外面的一圈;每一圈从左上角开始,按照顺时针、逆时针、顺时针……的顺序填。
作为小 X \text X X 的助手,他希望你帮助他以相同的规律填上旁边 n × n n\times n n×n 的空白方阵。这里方阵是数字正方形的简称,通常用二维数组来存放其中的数字。

输入格式

输入数据仅有一行,包含一个正整数 n n n ,表示方阵的边长,即每行每列有多少个数。

输出格式

输出仅 n n n 行,每行 n n n 个正整数,相邻两数之间严格用一个空格隔开。

样例输入

6

样例输出

1 2 3 4 5 6
20 21 32 31 30 7
19 22 33 34 29 8
18 23 36 35 28 9
17 24 25 26 27 10
16 15 14 13 12 11

提示

数据规模:
本题共有 10 10 10 个测试点,每个测试点 10 10 10 分:
对于测试点 1 1 1 n = 1 n=1 n=1;对于测试点 2 2 2 n = 2 n=2 n=2
对于测试点 3 3 3 n = 3 n=3 n=3;对于测试点 4 4 4 n = 4 n=4 n=4
对于测试点 5 5 5 n = 7 n=7 n=7;对于测试点 6 6 6 n = 8 n=8 n=8
对于测试点 7 7 7 n = 10 n=10 n=10;对于测试点 8 8 8 n = 15 n=15 n=15
对于测试点 9 9 9 n = 25 n=25 n=25;对于测试点 10 10 10 n = 50 n=50 n=50

与 2-1 类似。


2-5. 阶乘之和

题目描述

用高精度计算出 S = 1 ! + 2 ! + 3 ! + ⋯ + n ! S = 1! + 2! + 3! + \cdots + n! S=1!+2!+3!++n! n ≤ 50 n \le 50 n50)。
其中 ! 表示阶乘,定义为 n ! = n × ( n − 1 ) × ( n − 2 ) × ⋯ × 1 n!=n\times (n-1)\times (n-2)\times \cdots \times 1 n!=n×(n1)×(n2)××1。例如, 5 ! = 5 × 4 × 3 × 2 × 1 = 120 5! = 5 \times 4 \times 3 \times 2 \times 1=120 5!=5×4×3×2×1=120

输入格式

一个正整数 n n n

输出格式

一个正整数 S S S,表示计算结果。

样例输入

3

样例输出

9

提示

对于 100 % 100 \% 100% 的数据, 1 ≤ n ≤ 50 1 \le n \le 50 1n50

假如你不会高精度(雾),可以先用 Python 计算答案然后存进表中。



3. 打表题选——打表找规律

这些题目,我们可以通过把答案打一个表,然后寻找其中的规律。

3-1. 无穷的序列

题目描述

有一个无穷序列如下:
110100100010000100000 \texttt{110100100010000100000} 110100100010000100000
请你找出这个无穷序列中指定位置上的数字。

输入格式

第一行一个正整数 N N N ,表示询问次数;
接下来的 N N N 行每行一个正整数 A i A_i Ai A i A_i Ai 表示在序列中的位置。

输出格式

输出为 N N N 行,每行为 0 0 0 l l l ,表示序列第 A i A_i Ai 位上的数字。

样例输入

4
3
14
7
6

样例输出

0
0
1
0

提示

对于 100 % 100\% 100% 的数据, N ≤ 1   500   000 N \leq 1\,500\,000 N1500000 A i ≤ 1 0 9 A_i≤10^9 Ai109

我们可以通过打表,来列举出所有是 1 1 1 的位: 1 , 2 , 4 , 7 , 11 , 16 , 22 , ⋯ 1,2,4,7,11,16,22,\cdots 1,2,4,7,11,16,22,
我们发现,第 n n n 个就是 1 + 1 + 2 + 3 + 4 + 5 + ⋯ + n = n ( n + 1 ) 2 + 1 1+1+2+3+4+5+\cdots+n=\frac{n(n+1)}{2}+1 1+1+2+3+4+5++n=2n(n+1)+1
故对于第 n n n 个是不是 1 1 1,只要判断 2 ( n − 1 ) × ( 2 ( n − 1 ) + 1 ) 2 = n − 1 \frac{\sqrt{2(n-1)}\times(\sqrt{2(n-1)}+1)}{2}=n-1 22(n1) ×(2(n1) +1)=n1 即可。
AC Code:

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n;
		scanf("%d",&n);
		n--;
		printf("%d\n",int(sqrt(n*2))*int(sqrt(n*2)+1)==n*2);
	} 
	return 0;
}

3-2. 数列之异或

题目描述

1 ⨁ 2 ⨁ ⋯ ⨁ N 1 \bigoplus 2 \bigoplus\cdots\bigoplus N 12N 的值。
A ⨁ B A \bigoplus B AB A A A , B B B 按位异或。

输入格式

1 个整数 N N N

输出格式

1 个整数,表示所求的值。

样例输入

3

样例输出

0

提示

  • 对于50% 的数据, 1 ≤ N ≤ 1 0 6 1 \le N \le 10^6 1N106
  • 对于100% 的数据, 1 ≤ N ≤ 1 0 18 1 \le N \le 10^{18} 1N1018

对于这道题,我们先从 1 1 1 打表找规律: 1 , 3 , 0 , 4 , 1 , 7 , 0 , 8 , 1 , 11 , 0 , 12 , ⋯ 1,3,0,4,1,7,0,8,1,11,0,12,\cdots 1,3,0,4,1,7,0,8,1,11,0,12,
我们把其四个四个分成一组: ( 1 , 3 , 0 , 4 ) , ( 1 , 7 , 0 , 8 ) , ( 1 , 11 , 0 , 12 ) , ⋯ (1,3,0,4),(1,7,0,8),(1,11,0,12),\cdots (1,3,0,4),(1,7,0,8),(1,11,0,12),
会发现,每组的第一、三个分别为 1 , 0 1,0 1,0;第二、四个分别为 n + 1 , n n+1,n n+1,n
AC Code:

#include<bits/stdc++.h>
using namespace std;

int main()
{
	long long n;
	cin>>n;
	long long ans[]={1,n+1,0,n};
	cout<<ans[(n-1)%4];
 	return 0;
}


4. 打表题选——间接打表

这些题目,我们可以在某些操作上进行打表,方便求解。

4-1. 马的遍历

题目描述

有一个 n × m n \times m n×m 的棋盘,在某个点 ( x , y ) (x, y) (x,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。

输入格式

输入只有一行四个整数,分别为 n , m , x , y n, m, x, y n,m,x,y

输出格式

一个 n × m n \times m n×m 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 − 1 -1 1)。

样例输入

3 3 1 1

样例输出

0    3    2    
3    -1   1    
2    1    4

提示

对于全部的测试点,保证 1 ≤ x ≤ n ≤ 400 1 \leq x \leq n \leq 400 1xn400 1 ≤ y ≤ m ≤ 400 1 \leq y \leq m \leq 400 1ym400

显然,我们可以 bfs 求解。
但是马有 8 8 8 种走法,将每种走法都写一遍会很烦。
于是,我们可以用 X [ ] \text X[] X[] 记第 i i i 种时 x x x 的变化, Y [ ] \text Y[] Y[] 同理。
AC Code:

#include<bits/stdc++.h>
using namespace std;

const int X[]={1,1,2,2,-1,-1,-2,-2};
const int Y[]={2,-2,1,-1,2,-2,1,-1};
int n,m,sx,sy,ans[405][405],qx[160005],qy[160005];

void bfs()
{
	int h=1,t=1;
	qx[h]=sx;
	qy[h]=sy;
	ans[sx][sy]=0;
	while(h<=t)
	{
		int x=qx[h];
		int y=qy[h];
		for(int i=0;i<8;i++)
		{
			int x_=x+X[i];
			int y_=y+Y[i];
			//...
		}
		h++;
	}
}

int main()
{
	//...
}

4-2. 靶形数独

题目描述

小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低。但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,Z 博士拿出了他最近发明的“靶形数独”,作为这两个孩子比试的题目。
靶形数独的方格同普通数独一样,在 9 9 9 格宽且 9 9 9 格高的大九宫格中有 9 9 9 3 3 3 格宽且 3 3 3 格高的小九宫格(用粗黑色线隔开的)。在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入 1 1 1 9 9 9 的数字。每个数字在每个小九宫格内不能重复出现,每个数字在每行、每列也不能重复出现。但靶形数独有一点和普通数独不同,即每一个方格都有一个分值,而且如同一个靶子一样,离中心越近则分值越高。(如图)

上图具体的分值分布是:最里面一格(黄色区域)为 10 10 10 分,黄色区域外面的一圈(红色区域)每个格子为 9 9 9 分,再外面一圈(蓝色区域)每个格子为 8 8 8 分,蓝色区域外面一圈(棕色区域)每个格子为 7 7 7 分,最外面一圈(白色区域)每个格子为 6 6 6 分,如上图所示。比赛的要求是:每个人必须完成一个给定的数独(每个给定数独可能有不同的填法),而且要争取更高的总分数。而这个总分数即每个方格上的分值和完成这个数独时填在相应格上的数字的乘积的总和。
总分数即每个方格上的分值和完成这个数独时填在相应格上的数字的乘积的总和。如图,在以下的这个已经填完数字的靶形数独游戏中,总分数为 2829。游戏规定,将以总分数的高低决出胜负。

由于求胜心切,小城找到了善于编程的你,让你帮他求出,对于给定的靶形数独,能够得到的最高分数。

输入格式

一共 9 9 9 行。每行 9 9 9 个整数(每个数都在 0 ∼ 9 0 \sim 9 09 的范围内),表示一个尚未填满的数独方格,未填的空格用“ 0 0 0”表示。每两个数字之间用一个空格隔开。

输出格式

输出共 1 1 1 行。输出可以得到的靶形数独的最高分数。如果这个数独无解,则输出整数 − 1 -1 1

样例输入 1

7 0 0 9 0 0 0 0 1 
1 0 0 0 0 5 9 0 0 
0 0 0 2 0 0 0 8 0 
0 0 5 0 2 0 0 0 3 
0 0 0 0 0 0 6 4 8 
4 1 3 0 0 0 0 0 0 
0 0 7 0 0 2 0 9 0 
2 0 1 0 6 0 8 0 4 
0 8 0 5 0 4 0 1 2

样例输出 1

2829

样例输入 2

0 0 0 7 0 2 4 5 3 
9 0 0 0 0 8 0 0 0 
7 4 0 0 0 5 0 1 0 
1 9 5 0 8 0 0 0 0 
0 7 0 0 0 0 0 2 5 
0 3 0 5 7 9 1 0 8 
0 0 0 6 0 1 0 0 0 
0 6 0 9 0 0 0 0 1 
0 0 0 0 0 0 0 0 6

样例输出 2

2852

提示

  • 对于 40 % 40\% 40% 的数据,数独中非 0 0 0 数的个数不少于 30 30 30
  • 对于 80 % 80\% 80% 的数据,数独中非 0 0 0 数的个数不少于 26 26 26
  • 对于 100 % 100\% 100% 的数据,数独中非 0 0 0 数的个数不少于 24 24 24

众所周知,这是一道经典的 dfs 剪枝题。
对于计算分值时,我们也可以打表(具体看代码)。
AC Code:

#include<bits/stdc++.h>
using namespace std;

const int PTS[15][15]={{6,6,6,6,6,6,6,6,6},
                       {6,7,7,7,7,7,7,7,6},
					   {6,7,8,8,8,8,8,7,6},
					   {6,7,8,9,9,9,8,7,6},
					   {6,7,8,9,10,9,8,7,6},
					   {6,7,8,9,9,9,8,7,6},
					   {6,7,8,8,8,8,8,7,6},
					   {6,7,7,7,7,7,7,7,6},
					   {6,6,6,6,6,6,6,6,6}};
struct node{
	int s,h;
}zr[15];
int a[15][15],ans=-1;
bool h[15][15],l[15][15],g[15][15];

bool cmp(node x,node y)
{
	//...
}

int f()
{
	int res=0;
	for(int i=1;i<=9;i++)
	{
		for(int j=1;j<=9;j++)
		{
			res+=PTS[i-1][j-1]*a[i][j];
		}
	}
	return res;
}

void dfs(int now,int x,int y,int s)
{
	//...
}

int main()
{
    //...
    return 0;
}

4-3. 生活大爆炸版石头剪刀布

题目描述

石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头。如果两个人出拳一样,则不分胜负。在《生活大爆炸》第二季第 8 集中出现了一种石头剪刀布的升级版游戏。
升级版游戏在传统的石头剪刀布游戏的基础上,增加了两个新手势:
斯波克:《星际迷航》主角之一。
蜥蜴人:《星际迷航》中的反面角色。
这五种手势的胜负关系如表一所示,表中列出的是甲对乙的游戏结果。

现在,小 A 和小 B 尝试玩这种升级版的猜拳游戏。已知他们的出拳都是有周期性规律的,但周期长度不一定相等。例如:如果小 A 以“石头-布-石头-剪刀-蜥蜴人-斯波克”长度为 6 6 6 的周期出拳,那么他的出拳序列就是“石头-布-石头-剪刀-蜥蜴人-斯波克-石头-布-石头-剪刀-蜥蜴人-斯波克-…”,而如果小 B 以“剪刀-石头-布-斯波克-蜥蜴人”长度为 5 5 5 的周期出拳,那么他出拳的序列就是“剪刀-石头-布-斯波克-蜥蜴人-剪刀-石头-布-斯波克-蜥蜴人-…”
已知小 A 和小 B 一共进行 N N N 次猜拳。每一次赢的人得 1 1 1 分,输的得 0 0 0 分;平局两人都得 0 0 0 分。现请你统计 N N N 次猜拳结束之后两人的得分。

输入格式

第一行包含三个整数: N , N A , N B N,N_A,N_B N,NA,NB,分别表示共进行 N N N 次猜拳、小 A 出拳的周期长度,小 B 出拳的周期长度。数与数之间以一个空格分隔。
第二行包含 N A N_A NA 个整数,表示小 A 出拳的规律,第三行包含 N B N_B NB 个整数,表示小 B 出拳的规律。其中, 0 0 0 表示“剪刀”, 1 1 1 表示“石头”, 2 2 2 表示“布”, 3 3 3 表示“蜥蜴人”,$4 $表示“斯波克”。数与数之间以一个空格分隔。

输出格式

输出一行,包含两个整数,以一个空格分隔,分别表示小 A、小 B 的得分。

样例输入 1

10 5 6
0 1 2 3 4
0 3 4 2 1 0

样例输出 1

6 2

样例输入 2

9 5 5
0 1 2 3 4
1 0 3 2 4

样例输出 2

4 4

提示

对于 100 % 100\% 100%的数据, 0 < N ≤ 200 , 0 < N A ≤ 200 , 0 < N B ≤ 200 0 < N \leq 200, 0 < N_A \leq 200, 0 < N_B \leq 200 0<N200,0<NA200,0<NB200

这题中,对于猜拳胜负情况,我们亦可打一个表,把每种胜负情况都记下来。
AC Code:

#include<bits/stdc++.h>
using namespace std;

const int A[5][5]={{0,0,1,1,0},{1,0,0,1,0},{0,1,0,0,1},{0,0,1,0,1},{1,1,0,0,0}};

int main()
{
	//...
	for(int i=0;i<n;i++)
	{
		ans1+=A[a[i%na]][b[i%nb]];
		ans2+=A[b[i%nb]][a[i%na]];
	}
	//...
	return 0;
}


5. 打表优化

有时,打的表代码长度很长,导致 MLE。通常我们有以下的优化:

  • 部分打表。对于可以在规定时间计算的答案,我们直接算;其余的输入的数均打成一个表。
  • 十六进制优化。如果输出的是数字,我们可以对部分表进行十六进制的转换以缩短代码长度(具体方法参见 洛谷 P8115)。类似地,我们甚至可以三十六进制优化。
  • 分段打表。也是比较常用的方法,要有分块基础。与分块类似,将答案分成若干块,对于每一块先计算答案。最后输出时利用与分块类似的做法进行处理答案(详见 OI Wiki)。
  • 差分优化。类似十六进制优化。
  • 二次差分优化
  • ……

CSP 2022-J2/S2 将至,愿大家考出好成绩!

  • 11
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
对于Java对GPIB接口控制,可以使用NI-VISA库来进行控制。NI-VISA(National Instruments Virtual Instrument Software Architecture)是一种通用的VISA编程接口,可以用来控制各种类型的仪器和设备,包括GPIB、USB、以太网、串口等等。 以下是一个使用NI-VISA库来进行GPIB通信的Java示例代码: ```java import java.util.concurrent.TimeUnit; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.ptr.IntByReference; import visa32.*; public class GPIBControl { private static final int GPIB_ADDRESS = 4; // GPIB地址 private static final int BUFFER_SIZE = 1024; // 缓冲区大小 public static void main(String[] args) { // 初始化NI-VISA库 VisaLibrary visaLibrary = (VisaLibrary) Native.loadLibrary("visa32", VisaLibrary.class); visaLibrary.viOpenDefaultRM(); // 打开GPIB设备 String deviceName = "GPIB0::" + GPIB_ADDRESS + "::INSTR"; Pointer instrument = new Memory(GpibLibrary.ViUInt32.SIZE); visaLibrary.viOpen(visaLibrary.getResourceManager(), deviceName, new GpibLibrary.ViAccessMode(GpibLibrary.VI_NO_LOCK), new GpibLibrary.ViUInt32(0), instrument); Pointer session = instrument.getPointer(0); // 设置超时时间 visaLibrary.viSetAttribute(new GpibLibrary.ViSession(session), new GpibLibrary.ViAttrState(GpibLibrary.VI_TMO_VALUE), new GpibLibrary.ViUInt32(5000)); // 写入命令 String command = "*IDN?"; visaLibrary.viWrite(new GpibLibrary.ViSession(session), command.getBytes(), new GpibLibrary.ViUInt32(command.length()), new IntByReference()); // 读取响应 byte[] buffer = new byte[BUFFER_SIZE]; visaLibrary.viRead(new GpibLibrary.ViSession(session), buffer, new GpibLibrary.ViUInt32(BUFFER_SIZE), new IntByReference()); String response = new String(buffer).trim(); System.out.println("Instrument response: " + response); // 关闭设备 visaLibrary.viClose(new GpibLibrary.ViSession(session)); visaLibrary.viClose(visaLibrary.getResourceManager()); } } ``` 在这个示例中,我们使用NI-VISA库来打开GPIB设备,设置超时时间,写入命令并读取响应。需要注意的是,GPIB_ADDRESS变量需要设置为实际的GPIB地址,BUFFER_SIZE变量可以根据需要进行调整。 希望这个示例代码能够对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值