レベル 1: アレンジメント
サンプル入力
4 2
サンプル出力
A B
A C
A D
B A
B C
B D
C A
C B
C D
D A
D B
D C
分析:
これは、あらゆる状況に対する列挙型の解決コードであることに注意してください
。
//#include<bits/stdc++.h>
#include<stdio.h>
//using namespace std;
int m,n;
int an[10010],a[10010],ck[10010];
void cal(int x){
if(x==n){
for(int i = 0;i<n;i++){
printf("%c",an[i]); if(i!=n-1) printf(" ");
}
printf("\n");
return;
}else{
for(int i = 0 ; i < m;i++){
if(ck[i]!=1){
an[x] = a[i];
ck[i] = 1;
cal(x+1);
ck[i] = 0;
}
}
}
}
int main(){
scanf("%d%d",&m,&n);
for(int i = 0; i <m;i++){
a[i] = i+ 'A';
ck[i] = 0;
}
cal(0);
return 0;
}
レベル 2: サブセット
サンプル入力
5 10
2 2 6 5 4
サンプル出力
2 2 6
6 4
アイデア:サブセット ツリーを使用して、条件を満たすサブセットの制限条件を見つけるだけです。
解決策コード:
#include<stdio.h>
//#include<bits/stdc++.h>
//using namespace std;
int a[20],an[20], ck[20];
int n,c;
int f = 0;
void solve(int x,int sum,int st){
if(sum>c) return; //剪枝
if(sum==c){
f = 1;//标记是不是 存在解
for(int i = 0; i <x;i++){
//输出
printf("%d",an[i]); if(i!=x-1) printf(" ");
} printf("\n");
return;
}else{
for(int i = st; i <n;i++){
//解空间树结点下的结点 是有范围的
if(ck[i]!=1){
an[x] = a[i]; ck[i] = 1;
//cout<<"i: "<<i<<" "<<a[i]<<" "<<sum<<" "<<ck[i]<<endl;
solve(x+1,sum+a[i],i);
ck[i] = 0;
}
}
}
}
int main(){
scanf("%d%d",&n,&c);
for(int i = 0; i < n;i++) scanf("%d",&a[i]);
solve(0,0,0);
if(!f) printf("No Solution!");
return 0;
}
レベル 3: TSP の質問
入力形式:
最初の行に「n」と入力します。これは、n 個の都市があることを意味します。
次に、n 行の各行に n 個の数値を入力します。i 行、j 列の値は、都市 i から都市 j までの距離を表します。0 は都市間に接続がないことを示します。注: 始点と終点は両方とも 1 n<
です
。 7、都市間の距離
出力形式は
100 を超えません。最初の行は最小移動コストを出力し、
2 行目は移動経路に入ります
(最短の移動経路が 1 つだけであることが保証されます)。
サンプル入力
4
0 30 6 4
30 0 5 10
6 5 0 20
4 10 20 0
サンプル出力
25
1 3 2 4 1
コード 1:
// #include<bits/stdc++.h>
// using namespace std;
#include<stdio.h>
int a[110][110];
int n;
int f[110],p[110],pd[110];
int minn = 1000010,sum = 0,len = 1;
void solve(int x){
if(len==n&&a[x][1]!=0){
//就是 最后要回到起点
if(sum+a[x][1]<minn){
for(int i = 0; i<n;i++){
pd[i] = p[i]; //存一下 不断更新 找最小的
}
minn = sum +a[x][1];
}
}
if(sum>minn) return ;
if(len<n){
for(int j = 1; j <= n;j++){
if(f[j]==0&&a[x][j]!= 0){
sum += a[x][j]; p[len] = j;
len++; f[j] = 1;
solve(j);
f[j] = 0;
len--;
sum -= a[x][j];
}
}
}
}
int main(){
scanf("%d",&n);
for(int i = 1; i <= n;i++){
for(int j = 1; j <= n;j++){
scanf("%d",&a[i][j]);
}
}
f[1] = 1; solve(1);
printf("%d\n",minn);
printf("1 ");
for(int i = 1; i < n;i++) printf("%d ",pd[i]);
printf("1");
return 0;
}
コード 2:
#include <stdio.h>
#define MAX 100
int n;
int b[8]={
1,2,3,4,5,6,7};
int a[MAX][MAX],x[8];
int mindis=1000;
void swap(int &a,int &b)
{
int t=a;
a=b;
b=t;
}
void dfs(int i,int dis)
{
if(dis>=mindis)
return;
else if(i==n)
{
if(dis+a[b[i-1]][1]<mindis)
{
mindis=dis+a[b[i-1]][1];
for(int j=1;j<n;j++)
x[j]=b[j];
}
return;
}
else
{
for(int j=i;j<n;j++)
{
swap(b[i],b[j]);
dfs(i+1,dis+a[b[i-1]][b[i]]);
swap(b[i],b[j]);
}
}
}
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
scanf("%d",&a[i][j]);
}
dfs(1,0);
printf("%d\n",mindis);
printf("1");
for(int i=1;i<n;i++)
printf(" %d",x[i]);
printf(" 1");
return 0;
}
レベル 4: n クイーン問題
タスクの説明:
N*N の正方形のチェス盤上に N 個のクイーンを配置し、互いに攻撃しないようにします (つまり、どの 2 つのクイーンも同じ行、同じ列に配置することはできず、同じ位置に配置することもできません)。チェス盤の境界線から 45 度の角度。オンライン。
あなたのタスクは、指定された N に対して正当な配置方法がいくつあるかを調べることです。
入力形式に
は複数の行があり、各行には正の整数 N≤10 があり、その数を示します。チェス盤とクイーン; N=0 の場合、終了を示します
出力形式に
は複数の行があり、各行は正の整数を持ち、入力行に対応するクイーンの異なる配置の数を示します。
タスクの説明:
N*N の正方形のチェス盤上に N 個のクイーンを配置し、互いに攻撃しないようにします (つまり、どの 2 つのクイーンも同じ行、同じ列に配置することはできず、同じ位置に配置することもできません)。チェス盤の境界線から 45 度の角度。オンライン。
あなたの課題は、指定された N に対して正当な配置方法がいくつあるかを見つけることです。
入力形式
複数の行があり、各行にはチェス盤とクイーンの数を示す正の整数 N≤10 があり、N=0 の場合は終了を意味します。
出力形式に
は複数の行があり、各行は正の整数を持ち、入力行に対応するクイーンの異なる配置の数を示します。
サンプル入力
1
8
5
0
サンプル出力
1
92
10
アイデア:
実際、スペース ツリーを解く際の制限は、この解セットの現在のノードの行、スラッシュ、およびバックスラッシュに既にクイーンが存在するかどうかを判断することです。
解決策コード:
//#include<bits/stdc++.h>
#include<stdio.h>
//using namespace std;
const int N = 20;
int n;
int col[N],dg[N],udg[N];
int ans;
void solve(int u){
if(u==n){
ans++; return;
}else{
for(int i = 0; i< n;i++){
if(!col[i]&&!dg[u+i]&&!udg[u+n-i]){
col[i] = dg[u+i] = udg[u+n-i] = true;
solve(u+1);
col[i] = dg[u+i] = udg[u+n-i] = false;
}
}
}
}
int main(){
while(~scanf("%d",&n)&&n){
ans = 0;
solve(0);
printf("%d\n",ans);
}
return 0;
}
レベル 5: 0-1 バックパック
**アイデア:** 動的プログラミングについては、多くを語ることはありません。
解決策コード:
#include<stdio.h>
// #include<bits/stdc++.h>
// using namespace std;
int n,c,w[110],v[110];
int f[110][110];
int main(){
scanf("%d%d",&n,&c);
for(int i = 1; i <= n;i++){
scanf("%d",&w[i]);
}
for(int i = 1; i <= n;i++){
scanf("%d",&v[i]);
}
for(int i = 1; i <= n;i++){
for(int j = 0; j <= c;j++){
f[i][j] = f[i-1][j];
if(j>=w[i]&&(f[i-1][j-w[i]]+v[i] > f[i][j])) f[i][j] = f[i-1][j-w[i]]+v[i] ;
}
}
printf("%d",f[n][c]);
return 0;
}