(一)n皇后问题
洛谷 P1219 [USACO1.5]八皇后 Checker Challenge
照着教材上的代码写,最后一个测试点(n=13)不开O2过不了。
#include <bits/stdc++.h>
using namespace std;
const int N=25;
int n,x[N];
long long sum;
void out(int x[])
{
for(int i=1;i<=n;i++)
i==n?printf("%d\n",x[i]):printf("%d ",x[i]);
}
bool check(int i)
{
for(int j=1;j<i;j++)
if(abs(i-j)==abs(x[i]-x[j])||x[i]==x[j])return 0;
return 1;
}
void dfs(int k)
{
if(k>n)
{
sum++;
if(sum<=3)out(x);
return;
}
for(int i=1;i<=n;i++)
{
x[k]=i;
if(check(k))
dfs(k+1);
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>n;
dfs(1);
printf("%d\n",sum);
return 0;
}
(二)01背包-回溯法
注释掉的部分是求最优解的代码。回溯法,即使剪枝也只能拿30分:
#include <bits/stdc++.h>
using namespace std;
const int N=110;
int n,c,mx,w[N],v[N],sum[N];
//int x[N],ans[N];
void dfs(int k,int rest,int cv) // 第k个物品,背包剩余容量rest,当前已获得价值cv
{
if(k>n)
{
if(cv>mx)
{
mx=cv; // 更新最优值
//for(int i=1;i<=n;i++) // 更新最优解
//ans[i]=x[i];
}
return;
}
if(rest>=w[k]) // 能放,进入左子树
{
//x[k]=1;
dfs(k+1,rest-w[k],cv+v[k]);
}
if(sum[n]-sum[k]+cv>mx) // 不放且满足限界函数,进入右子树
{
//x[k]=0;
dfs(k+1,rest,cv);
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>c>>n;
for(int i=1;i<=n;i++)
{
cin>>w[i]>>v[i];
sum[i]=sum[i-1]+v[i];
}
dfs(1,c,0);
printf("%d\n",mx);
//for(int i=1;i<=n;i++)
//i==n?printf("%d\n",ans[i]):printf("%d ",ans[i]);
return 0;
}
/*
10 5
1 2
2 5
6 7
3 4
5 6
ans:15
0 1 0 1 1
*/
记忆化搜索(AC):
#include <bits/stdc++.h>
using namespace std;
const int N=1110;
int n,c,w[N],v[N],sum[N],dp[N][N];
int x[N],ans[N];
int dfs(int k,int rest) // 第k个物品
{
if(dp[k][rest]!=-1)return dp[k][rest];
if(k>n)return 0;
int ret1=0,ret2=0;
if(rest>=w[k]) // 能放,进入左子树
{
x[k]=1;
ret1=dfs(k+1,rest-w[k])+v[k];
}
ret2=dfs(k+1,rest);
return dp[k][rest]=max(ret1,ret2);
}
int main()
{
ios::sync_with_stdio(false);
cin>>c>>n;
for(int i=1;i<=n;i++)
cin>>w[i]>>v[i];
memset(dp,-1,sizeof(dp));
int mx=dfs(1,c);
printf("%d\n",mx);
return 0;
}
/*
10 5
1 2
2 5
6 7
3 4
5 6
ans:15
0 1 0 1 1
20 5
1 2
2 1
3 5
8 4
9 26
ans:35
0 0 1 1 1
*/
(三)旅行售货员问题
貌似是状态压缩DP的题,用DFS剪枝,骗了90分,还差最后一个测试点
// 旅行售货员问题
#include <bits/stdc++.h>
using namespace std;
const int N=1e3+10,inf=0x7f7f7f7f;
int n,r,bestc,nowc,x[N],w[N][N],mi[N],sum[N];
void out(int x[])
{
for(int i=1;i<=n;i++)
i==n?printf("%d\n",x[i]):printf("%d ",x[i]);
}
void dfs(int i) // 从第i-1个点开始能否找到下一个可行点
{
if(i==n)
{
//out(x);
if(w[x[n-1]][x[n]]&&w[x[n]][1])
{
int tmp=nowc+w[x[n-1]][x[n]]+w[x[n]][1];
bestc=min(bestc,tmp);
}
return;
}
for(int j=i;j<=n;j++)
{
int &u1=x[i-1];
int &u2=x[i];
int &v=x[j];
if(w[u1][v]&&nowc+w[u1][v]<bestc&&nowc+r<bestc)
// i<=j<=n中能否找到一个x[j],使得x[i-1]能到x[j]
// 如果能就把x[j]放到x[i]的位置,然后继续找[i+1,n]排列
{
nowc+=w[u1][v];
r-=w[u1][v];
swap(u2,v);
dfs(i+1);
swap(u2,v);
nowc-=w[u1][v];
r+=w[u1][v];
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>n;
memset(mi,inf,sizeof(mi));
bestc=inf;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>w[i][j];
if(w[i][j])mi[i]=min(mi[i],w[i][j]);
}
r+=mi[i];
}
for(int i=1;i<=n;i++)
x[i]=i;
dfs(2);
printf("%d\n",bestc);
return 0;
}
/*
4
0 30 6 4
30 0 5 10
6 5 0 20
4 10 20 0
ans:25
*/
测试数据:
input1
19
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0
output1
19
input2
20
0 487 975 636 836 688 546 411 748 199 302 808 945 34 631 462 644 551 401 128
521 0 203 268 533 102 906 424 871 173 256 450 7 283 80 266 315 451 327 960
567 758 0 612 128 509 206 3 417 554 576 776 293 857 928 998 583 44 25 274
164 848 953 0 95 696 825 962 360 933 390 159 20 76 923 29 110 323 742 904
105 360 246 232 0 513 498 482 2 643 276 333 83 375 244 711 778 226 190 925
106 901 679 994 628 0 932 116 993 260 224 654 387 150 984 61 135 571 574 696
186 412 397 611 822 386 0 144 720 807 840 66 99 794 862 466 195 510 570 758
20 437 896 787 717 851 439 0 20 519 683 363 672 887 702 191 861 276 656 460
253 747 384 282 353 245 323 261 0 611 943 977 336 751 805 397 645 697 354 210
65 550 816 327 259 925 245 624 116 0 16 947 278 975 864 881 903 995 988 335
59 879 802 26 177 956 931 136 647 1000 0 979 109 176 170 136 285 334 247 380
79 509 30 199 89 565 995 523 996 474 639 0 913 426 868 780 478 961 818 771
25 261 283 977 188 321 933 444 495 404 141 731 0 359 754 160 873 675 23 670
861 397 846 5 836 590 732 87 404 694 733 306 419 0 558 735 426 583 900 803
107 195 711 172 677 417 668 887 403 338 729 580 929 374 0 320 35 440 697 926
344 339 556 54 926 787 231 942 295 929 292 132 918 927 836 0 613 375 339 77
161 686 640 980 99 713 607 460 116 937 333 133 23 717 445 254 0 227 635 486
383 349 942 16 636 911 667 138 420 558 805 933 729 708 422 470 222 0 491 786
373 51 811 751 602 41 899 365 786 411 72 475 495 788 587 919 241 340 0 587
903 629 674 219 265 966 890 228 665 176 515 52 565 3 530 490 431 357 173 0
output2
1444