@

(一)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背包-回溯法

洛谷 P1048 采药

注释掉的部分是求最优解的代码。回溯法,即使剪枝也只能拿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
*/

(三)旅行售货员问题

洛谷 P1171 售货员的难题

貌似是状态压缩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