————————————————
原代码链接:https://blog.youkuaiyun.com/guagua_de_xiaohai/article/details/88921307
————————————————
借用「偷吃了老鼠的土豆」的代码来当模板
1.题目描述
就解数独呗。
输入:
输入可能有多行
每行一个9x9的数独输入,0就是没有数字
输出:
输出解。
样例:
输入:
000000010400000000020000000000050407008000300001090000300400200050100000000806000
输出:
693784512487512936125963874932651487568247391741398625319475268856129743274836159
思路:
9*9的暴搜其实也很快
Dancing Link
详解:
https://www.jianshu.com/p/93b52c37cc65
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int N = 9;
const int maxn = N * N * N + 10;
const int maxnode = maxn * 4 + maxn + 10;
char g[maxn];
struct DLX
{
int n,m,sz;
int U[maxnode],D[maxnode],R[maxnode],L[maxnode],Row[maxnode],Col[maxnode];
int H[maxn],S[maxn];
int ansd,ans[maxn];
void init(int _n,int _m)
{
n = _n;
m = _m;
for(int i = 0;i <= m;i ++)
{
S[i] = 0;
U[i] = D[i] = i;
L[i] = i - 1;
R[i] = i + 1;
}
R[m] = 0;
L[0] = m;
sz = m;
for(int i = 1;i <= n;i ++)
{
H[i] = -1;
}
}
void Link(int r,int c)
{
++ S[Col[++ sz] = c];
Row[sz] = r;
D[sz] = D[c];
U[D[c]] = sz;
U[sz] = c;
D[c] = sz;
if(H[r] < 0) H[r] = L[sz] = R[sz] = sz;
else
{
R[sz] = R[H[r]];
L[R[H[r]]] = sz;
L[sz] = H[r];
R[H[r]] = sz;
}
}
void Remove(int c)
{
L[R[c]] = L[c];
R[L[c]] = R[c];
for(int i = D[c];i != c;i = D[i])
{
for(int j = R[i];j != i;j = R[j])
{
U[D[j]] = U[j];
D[U[j]] = D[j];
-- S[Col[j]];
}
}
}
void resume(int c)
{
for(int i = U[c];i != c;i = U[i])
{
for(int j = L[i];j != i;j = L[j])
{
++ S[Col[U[D[j]] = D[U[j]] = j]];
}
}
L[R[c]] = R[L[c]] = c;
}
bool Dance(int d)
{
if(R[0] == 0)
{
for(int i = 0;i < d;i ++)
{
g[(ans[i] - 1) / 9] = (ans[i] - 1) % 9 + '1';
}
for(int i = 0;i < N * N;i ++)
{
printf("%c",g[i]);
}
printf("\n");
return true;
}
int c = R[0];
for(int i = R[0];i != 0;i = R[i])
{
if(S[i] < S[c])
c = i;
}
Remove(c);
for(int i = D[c];i != c;i = D[i])
{
ans[d] = Row[i];
for(int j = R[i]; j != i;j = R[j]) Remove(Col[j]);
if(Dance(d + 1)) return true;
for(int j = L[i];j != i;j = L[j]) resume(Col[j]);
}
resume(c);
return false;
}
};
void place(int &r,int &c1,int &c2,int &c3,int &c4,int i,int j,int k)
{
r = (i * N + j) * N + k;
c1 = i * N + j + 1;
c2 = N * N + i * N + k;
c3 = N * N * 2 + j * N + k;
c4 = N * N * 3 + ((i / 3) * 3 + (j / 3)) * N + k;
}
DLX dlx;
int main()
{
// freopen("test1","r",stdin);
while(scanf("%s",g) != EOF)
{
dlx.init(N * N * N, N * N * 4);
int r,c1,c2,c3,c4;
for(int i = 0;i < N;i ++)
{
for(int j = 0;j < N;j ++)
{
for(int k = 1;k <= N;k ++)
{
if(g[i * N + j] == '0' || g[i * N + j] == '0' + k)
{
place(r,c1,c2,c3,c4,i,j,k);
dlx.Link(r,c1);
dlx.Link(r,c2);
dlx.Link(r,c3);
dlx.Link(r,c4);
}
}
}
}
dlx.Dance(0);
}
return 0;
}
/*
000000010400000000020000000000050407008000300001090000300400200050100000000806000
000000013020500000000000000103000070000802000004000000000340500670000200000010000
000000013400200000600000000000460500010000007200500000000031000000000420080000000
000000013400800000200000070000400900001000000060000000000501600380000200000070000
000000014000000203800050000000207000031000000000000650600000700000140000000300000
000000014000020000500000000010804000700000500000100000000050730004200000030000600
000000014000708000000000000104005000000200830600000000500040000030000700000090001
000000014008005000020000000000020705100000000000000800070000530600140000000200000
000000014008005000020000000000020805100000000000000700070000530600140000000200000
000000014008009000020000000000020805100000000000000700070000930600140000000200000
000000014700000000000500000090014000050000720000600000000900805600000900100000000
000000014790000000000200000000003605001000000000000200060000730200140000000800000
000000014970000000000200000000003605001000000000000200060000730200140000000800000
000000015000400070300060000800000200000104000400500000000023600010000000070000000
000000015000400070400000000609000300000100800000700000500030200000060040010000000
000000015000800070300000000408000300000100400000700000500040200000090060010000000
000000015000800070400000000609000300000100800000700000500030200000060040010000000
*/
到此结束,下面是用多线程来跑这个东西,没有用到线程池和线程同步:
C++多线程入门
https://blog.youkuaiyun.com/Kprogram/article/details/89472995?tdsourcetag=s_pctim_aiomsg#WaitForSingleObject_128
#include <iostream>
#include <cstdio>
#include <windows.h>
#include <fstream>
using namespace std;
//封装数独代码
const int N = 9;
const int maxn = N * N * N + 10;
const int maxnode = maxn * 4 + maxn + 10;
//多线程执行完后,为了不让他抢输出,用一个全局结果存起来最后再输出
char result[1010][100];
HANDLE cout_mutex;//互斥锁
struct DLX
{
int n,m,sz;
int U[maxnode],D[maxnode],R[maxnode],L[maxnode],Row[maxnode],Col[maxnode];
int H[maxn],S[maxn];
char g[maxn];
int ansd,ans[maxn];
void init(int _n,int _m)
{
n = _n;
m = _m;
for(int i = 0;i <= m;i ++)
{
S[i] = 0;
U[i] = D[i] = i;
L[i] = i - 1;
R[i] = i + 1;
}
R[m] = 0;
L[0] = m;
sz = m;
for(int i = 1;i <= n;i ++)
{
H[i] = -1;
}
}
void Link(int r,int c)//填数据到表上
{
++ S[Col[++ sz] = c];
Row[sz] = r;
D[sz] = D[c];
U[D[c]] = sz;
U[sz] = c;
D[c] = sz;
if(H[r] < 0) H[r] = L[sz] = R[sz] = sz;
else
{
R[sz] = R[H[r]];
L[R[H[r]]] = sz;
L[sz] = H[r];
R[H[r]] = sz;
}
}
void Remove(int c)
{
L[R[c]] = L[c];
R[L[c]] = R[c];
for(int i = D[c];i != c;i = D[i])
{
for(int j = R[i];j != i;j = R[j])
{
U[D[j]] = U[j];
D[U[j]] = D[j];
-- S[Col[j]];
}
}
}
void resume(int c)
{
for(int i = U[c];i != c;i = U[i])
{
for(int j = L[i];j != i;j = L[j])
{
++ S[Col[U[D[j]] = D[U[j]] = j]];
}
}
L[R[c]] = R[L[c]] = c;
}
bool Dance(int d)
{
if(R[0] == 0)
{
for(int i = 0;i < d;i ++)
{
g[(ans[i] - 1) / 9] = (ans[i] - 1) % 9 + '1';
}
/* for(int i = 0;i < N * N;i ++)
{
printf("%c",g[i]);
}
printf("\n");*/
return true;
}
int c = R[0];
for(int i = R[0];i != 0;i = R[i])
{
if(S[i] < S[c])
c = i;
}
Remove(c);
for(int i = D[c];i != c;i = D[i])
{
ans[d] = Row[i];
for(int j = R[i]; j != i;j = R[j]) Remove(Col[j]);
if(Dance(d + 1)) return true;
for(int j = L[i];j != i;j = L[j]) resume(Col[j]);
}
resume(c);
return false;
}
};
void place(int &r,int &c1,int &c2,int &c3,int &c4,int i,int j,int k)//把数据置换成对应条件
{
r = (i * N + j) * N + k;
c1 = i * N + j + 1;
c2 = N * N + i * N + k;
c3 = N * N * 2 + j * N + k;
c4 = N * N * 3 + ((i / 3) * 3 + (j / 3)) * N + k;
}
struct LEI//靠结构体把参数传进线程
{
int id;
char line[100];
};
int counter = 0;
DWORD WINAPI MyThread(LPVOID lpParamter)
{
// 把lpParamter当成void指针就完事儿了
//int *a = (int *)lpParamter;
//锁
// WaitForSingleObject(cout_mutex, INFINITE);
LEI *p = (LEI *)lpParamter;
// cout<<"id = "<< p->id <<"\n"<< p->line <<endl;
//释放锁
// ReleaseMutex(cout_mutex);
char g[100];
strcpy(g, p->line);
DLX dlx;
strcpy(dlx.g, p->line);
dlx.init(N * N * N, N * N * 4);
int r,c1,c2,c3,c4;
for(int i = 0;i < N;i ++)
{
for(int j = 0;j < N;j ++)
{
for(int k = 1;k <= N;k ++)
{
if(g[i * N + j] == '0' || g[i * N + j] == '0' + k)
{
place(r,c1,c2,c3,c4,i,j,k);
dlx.Link(r,c1);
dlx.Link(r,c2);
dlx.Link(r,c3);
dlx.Link(r,c4);
}
}
}
}
dlx.Dance(0);
strcpy(result[p->id], dlx.g);//结果存起来,先不着急输出
counter--;
return 0L;
}
int main()
{
ifstream in("test1000");//读文件数据
string line;
string a[1010];
int i=0;
cout_mutex = CreateMutex(NULL, FALSE, NULL);
LEI parameter[1010];//这里要开足空间,线程在重复调用的话会刷掉数据
while (getline (in, line)) // line中不包括每行的换行符
{
i++;
a[i]=line;
strcpy(parameter[i].line, line.c_str());
parameter[i].id = i;
LEI *p = ¶meter[i];//用指针结构体传参
counter++;//开辟一个线程就+1,最后结束一个线程-1
HANDLE hThread = CreateThread(NULL, 0, MyThread, p , 0, NULL);
}
while(counter>0){Sleep(500);printf("等待%d个未完成线程\n",counter);}//只有所有的都执行完了,才能集中输出
cout<<endl<<endl;
for(int j=1;j<=i;j++)
{
cout<<"id = "<<j<<endl;
cout<<a[j]<<endl;
cout<<result[j]<<endl;
}
cout << "----------------------------\n";
return 0;
}