用mips汇编实现哈密尔顿回路

用mips汇编实现哈密尔顿回路.

哈密顿回路是一个非常经典的问题

题目难度不大,虽然是np的但是只需要你写一个非多项式的实现算法。

我们先回顾一下怎么用c++实现

#include <bits/stdc++.h>

#define REP(I,A,B) for (int I=(A),I##_END_=(B);I<=I##_END_;I++)
#define FOR(I,A,B) for (int I=(A),I##_END_=(B);I<I##_END_;I++)
#define REPD(I,A,B) for (int I=(A),I##_END_=(B);I>=I##_END_;I--)

int n,m;
int cnt[101];

using namespace std;

int get_id(int x,int y){
	return (x-1)*n+y;
}

int mark;
int a[101];
int all=0;


void dfs(int p){
	if (p==n+1)
	{
		all |= cnt[ get_id( a[n],a[1] ) ];
		return ;
	}
	else
		for (int i=1;i<=n;i++)
			if (((mark>>i)&1)==0 && cnt[ get_id( a[p-1] , i) ] )
			{
				mark ^= 1<<i;
				a[p]=i;
				dfs(p+1);
				mark ^= 1<<i;
			}
}

int main(){
	scanf("%d%d",&n,&m);
	int x,y;
	REP(i,1,m)
	{
		scanf("%d%d",&x,&y);
		cnt[get_id(x,y)]=cnt[get_id(y,x)]=1;
	}

	mark=2;
	a[1]=1;
	dfs(2);
	printf("%d\n",all);

	return 0;
}

基本实现如下

.data
	array_had: .space 800
	array_a: .space 80
	char_space: .asciiz " "
	char_endl: .asciiz "\n"


.text

main:
	la $s0,array_had
	la $s1,array_a
#la $s2,int_n
#la $s3,int_m
#la $s4,int_all
#la $s5,int_mark
	li $s4,0
	li $s5,2
#one
	li $s6,1 

	li $v0,5
	syscall
	move $s2,$v0

	li $v0,5
	syscall
	move $s3,$v0

# for m
	li $t1,0
	for_m_st:
		beq $t1,$s3,for_m_ed
		nop

		li $v0,5
		syscall
		move $t6,$v0

		li $v0,5
		syscall
		move $t7,$v0

		move $a0,$t6
		move $a1,$t7
		
		jal get_id
		mul $v0,$v0,4
		add $t2,$s0,$v0 
		sw $s6,0($t2)

		#swap
		move $a0,$t7
		move $a1,$t6

		jal get_id
		mul $v0,$v0,4
		add $t2,$s0,$v0
		sw $s6,0($t2)

		addi $t1,$t1,1
		j for_m_st
		nop
	for_m_ed:

	sw $s6,4($s1)
	li $a0,2
	jal dfs

	move $a0,$s4
	li $v0,1
	syscall

	li $v0,10
	syscall

get_id:
	mul $a0,$a0,$s2
	add $v0,$a0,$a1
	jr $31

dfs:

	sw $ra,0($sp)
	subi $sp,$sp,4
	sw $a0,0($sp)
	subi $sp,$sp,4

	bgt $a0,$s2,if_check_then
	nop
	j if_check_end

	if_check_then:
		
		li $t1 1
		mul $t1,$t1,4
		add $t1,$t1,$s1
		lw $t1,0($t1)
		move $a0,$t1

		move $t1,$s2
		mul $t1,$t1,4
		add $t1,$t1,$s1
		lw $t1,0($t1)
		move $a1,$t1

		jal get_id
		mul $v0,$v0,4
		add $t1,$s0,$v0
		lw $t1,0($t1)
		or $s4,$s4,$t1

		addi $sp,$sp,4
		addi $sp,$sp,4
		lw $ra,0($sp)
		jr $31

	if_check_end:

	bne $a0,$0,dfs_work

	dfs_work:
		#for_dfs
		li $t1,1
		for_dfs_st:
			bgt $t1,$s2,for_dfs_ed
			nop

				sllv $t2,$s6,$t1
				and $t2,$s5,$t2
				seq $t2,$t2,0

				addi $sp,$sp,4
				lw $t3,0($sp)
				subi $sp,$sp,4
				sub $t3,$t3,1

				mul $t3,$t3,4
				add $t3,$t3,$s1
				lw $t3,0($t3)
				move $a0,$t3
				move $a1,$t1

				jal get_id
				mul $v0,$v0,4
				add $t3,$v0,$s0
				lw $t3,0($t3)
				
				and $t2,$t2,$t3

				beq $t2,$s6,if_mark_then
				nop
				j if_mark_end

				if_mark_then:

					# t3  = a0
					addi $sp,$sp,4
					lw $t3,0($sp)
					subi $sp,$sp,4

					sw $s5,0($sp)
					subi $sp,$sp,4

					sllv $t2,$s6,$t1
					or $s5,$s5,$t2

					mul $t2,$t3,4
					add $t2,$s1,$t2
					sw $t1,0($t2)

					sw $t1,0($sp)
					subi $sp,$sp,4

					addi $a0,$t3,1
					jal dfs

					addi $sp,$sp,4
					lw $t1,0($sp)

					addi $sp,$sp,4
					lw $s5,0($sp)

				if_mark_end:

			addi $t1,$t1,1
			j for_dfs_st
		for_dfs_ed:

			addi $sp,$sp,4
			addi $sp,$sp,4
			lw $ra,0($sp)
			jr $31

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是用MIPS汇编实现输出2022年日历的代码: ``` .data monthNames: .asciiz "JanFebMarAprMayJunJulAugSepOctNovDec" dayNames: .asciiz "SuMoTuWeThFrSa" year: .word 2022 monthDays: .word 31,28,31,30,31,30,31,31,30,31,30,31 leapMonthDays: .word 31,29,31,30,31,30,31,31,30,31,30,31 newline: .asciiz "\n" space: .asciiz " " .text main: # Print year la $a0, year lw $a0, ($a0) li $v0, 1 syscall la $a0, newline li $v0, 4 syscall # Check if it's a leap year li $t0, 0 lw $t1, year li $t2, 4 div $t1, $t2 mfhi $t3 beq $t3, $zero, leapYear # Not a leap year la $t4, monthDays # Print each month li $t5, 0 # month counter li $t6, 1 # day counter li $t7, 1 # weekday counter li $t8, 12 # number of months loop: # Print month name la $t9, monthNames add $t9, $t9, $t5 lb $a0, ($t9) li $v0, 11 syscall la $a0, space li $v0, 4 syscall # Print year and newline lw $a0, year li $v0, 1 syscall la $a0, newline li $v0, 4 syscall # Print day names la $a0, dayNames li $v0, 4 syscall la $a0, newline li $v0, 4 syscall # Print days of the month lw $t0, ($t4) # get number of days in month loop2: # Print spaces until first day of month beq $t6, 2, printDay sub $t6, $t6, 1 la $a0, space li $v0, 4 syscall b loop2 printDay: # Print day move $a0, $t6 li $v0, 1 syscall # Increment weekday counter addi $t7, $t7, 1 # Check if end of week beq $t7, 8, endOfWeek # Print space la $a0, space li $v0, 4 syscall # Increment day counter addi $t6, $t6, 1 # Check if end of month beq $t6, $t0, endOfMonth # Continue printing days of month j printDay endOfWeek: # Print newline la $a0, newline li $v0, 4 syscall # Reset weekday counter li $t7, 1 # Increment day counter addi $t6, $t6, 1 # Check if end of month beq $t6, $t0, endOfMonth # Continue printing days of month j printDay endOfMonth: # Print newline la $a0, newline li $v0, 4 syscall # Increment month counter addi $t5, $t5, 1 # Check if end of year beq $t5, $t8, endOfYear # Check if next month is February and it's a leap year bne $t5, 1, notFeb b leapYear notFeb: # Not February or not a leap year addi $t4, $t4, 4 # move to next month li $t6, 1 # reset day counter j loop endOfYear: # Exit program li $v0, 10 syscall leapYear: # Leap year la $t4, leapMonthDays # Print each month li $t5, 0 # month counter li $t6, 1 # day counter li $t7, 1 # weekday counter li $t8, 12 # number of months loop3: # Print month name la $t9, monthNames add $t9, $t9, $t5 lb $a0, ($t9) li $v0, 11 syscall la $a0, space li $v0, 4 syscall # Print year and newline lw $a0, year li $v0, 1 syscall la $a0, newline li $v0, 4 syscall # Print day names la $a0, dayNames li $v0, 4 syscall la $a0, newline li $v0, 4 syscall # Print days of the month lw $t0, ($t4) # get number of days in month loop4: # Print spaces until first day of month beq $t6, 2, printLeapDay sub $t6, $t6, 1 la $a0, space li $v0, 4 syscall b loop4 printLeapDay: # Print day move $a0, $t6 li $v0, 1 syscall # Increment weekday counter addi $t7, $t7, 1 # Check if end of week beq $t7, 8, leapEndOfWeek # Print space la $a0, space li $v0, 4 syscall # Increment day counter addi $t6, $t6, 1 # Check if end of month beq $t6, $t0, leapEndOfMonth # Continue printing days of month j printLeapDay leapEndOfWeek: # Print newline la $a0, newline li $v0, 4 syscall # Reset weekday counter li $t7, 1 # Increment day counter addi $t6, $t6, 1 # Check if end of month beq $t6, $t0, leapEndOfMonth # Continue printing days of month j printLeapDay leapEndOfMonth: # Print newline la $a0, newline li $v0, 4 syscall # Increment month counter addi $t5, $t5, 1 # Check if end of year beq $t5, $t8, endOfYear # Check if next month is February and it's not a leap year bne $t5, 1, notLeapFeb # February but not a leap year, move to next month addi $t4, $t4, 4 li $t6, 1 j loop3 notLeapFeb: # Not February or a leap year addi $t4, $t4, 4 # move to next month li $t6, 1 # reset day counter j loop3 ``` 请注意,该代码可能不是最优解决方案,并且可能需要进行额外的测试和调整才能确保正确性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值