1.数字组合
题目链接
题解:01背包方案数问题,直接套模板
java代码:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n,m;
n=sc.nextInt();
m=sc.nextInt();
int []a=new int[100+10];
for(int i=1;i<=n;i++)
a[i]=sc.nextInt();
int dp[]=new int[10000+10];
Arrays.fill(dp,0);
dp[0]=1;//0的时候什么都不选 只有一种方法
for(int i=1;i<=n;i++)
{
for(int j=m;j>=a[i];j--)
{
dp[j]+=dp[j-a[i]];//方法累加
}
}
System.out.println(dp[m]);
}
}
c++代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e2 + 7;
const int M = 1e4 + 7;
int dp[M], a[N];
int main() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> a[i];
dp[0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = m; j >= a[i]; j--) {
dp[j] += dp[j - a[i]];
}
}
printf("%d\n", dp[m]);
return 0;
}
2.自然数拆分Lunatic版
题目链接
题解:同上仍旧是方案数问题,只不过是完全背包
java代码:
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Scanner;
public class Main {
public static long Mod=2147483648L;
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n;
n=sc.nextInt();
long []dp=new long[4000+10];
Arrays.fill(dp,0);
dp[0]=1;
for(int i=1;i<n;i++)
for(int j=i;j<=n;j++)
dp[j] = (dp[j] + dp[j - i ]) % Mod;
System.out.println(dp[n]);
}
}
c++代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 4005;
long long n, dp[N], a[N];
int main()
{
cin >> n;
dp[0] = 1;
for(int i = 1; i <= n; i++)
for(int j = i; j <= n; j++)
dp[j] = (dp[j] + dp[j - i]) % 2147483648;
cout << (dp[n] > 0 ? dp[n]-1 : 2147483648) << endl;
return 0;
}
3.Jury Compromise
题目链接
题解:我们先不考虑|D-P|,就是让D+P最大,那么就是一个背包问题,因为背包每一个状态都是一个组合,我们只需要计算出每个组合此时的|D-P| ,也就是再背包原有的基础上再加一维记录此状态的|D-P|即可.
java代码:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class Main
{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n,m;
int dp[][][]=new int[850][250][30];
int a[]=new int[210];
int b[]=new int[210];
int t=1;
while(true){
n=sc.nextInt();
m=sc.nextInt();
for(int i=0;i<=840;i++)
for(int j=0;j<=230;j++)
Arrays.fill(dp[i][j],-9999);
if(n==0&&m==0)
break;
for(int i=1;i<=n;i++){
a[i]=sc.nextInt();
b[i]=sc.nextInt();
}
dp[400][0][0]=0;
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)//因为无法表示负数,我们把400当做0
for(int k=0;k<810;k++){
//类似01背包,多了一个考虑的因素
dp[k][i][j]=dp[k][i-1][j];
int now=a[i]-b[i];
if(k-now>800||k-now<0) continue;
if(j<1) continue;
dp[k][i][j]=Math.max(dp[k][i][j],dp[k-now][i-1][j-1]+a[i]+b[i]);
}
int base=400;
int v=0;
int res;
while(dp[base+v][n][m]<0&&dp[base-v][n][m]<0) v++;//从最小的找起,直到找到状态存在的
if(dp[base+v][n][m]>dp[base-v][n][m]) res=base+v;
else res=base-v;
int cnt=1;
int ans[]=new int[100];
while(m>0)//回事找方案
{
if(dp[res][n][m]==dp[res][n-1][m])n--;
else
{
ans[cnt++]=n;
if(res-(a[n]-b[n])>=0)
res-=(a[n]-b[n]);
n--;
m--;
}
}
int sp = 0, sd = 0;
for (int i = 0; i < cnt; i ++ )
{
sp += a[ans[i]];
sd += b[ans[i]];
}
System.out.println("Jury #"+t++);
System. out.println("Best jury has value "+sp+" for prosecution and value "+sd+" for defence:");
for(int i=cnt-1;i>0;i--)
System.out.printf(" "+ans[i]);
System.out.println("\n");
}
}
}
c++代码:
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 210, M = 810, base = 400;
int n, m;
int p[N], d[N];
int f[N][21][M];
int ans[N];
int main()
{
int T = 1;
while (scanf("%d%d", &n, &m), n || m)
{
for (int i = 1; i <= n; i ++ ) scanf("%d%d", &p[i], &d[i]);
memset(f, -0x3f, sizeof f);
f[0][0][base] = 0;
for (int i = 1; i <= n; i ++ )
for (int j = 0; j <= m; j ++ )
for (int k = 0; k < M; k ++ )
{
f[i][j][k] = f[i - 1][j][k];
int t = k - (p[i] - d[i]);
if (t < 0 || t >= M) continue;
if (j < 1) continue;
f[i][j][k] = max(f[i][j][k], f[i - 1][j - 1][t] + p[i] + d[i]);
}
int v = 0;
while (f[n][m][base - v] < 0 && f[n][m][base + v] < 0) v ++ ;
if (f[n][m][base - v] > f[n][m][base + v]) v = base - v;
else v = base + v;
int cnt = 0;
int i = n, j = m, k = v;
while (j)
{
if (f[i][j][k] == f[i - 1][j][k]) i -- ;
else
{
ans[cnt ++ ] = i;
k -= (p[i] - d[i]);
i --, j -- ;
}
}
int sp = 0, sd = 0;
for (int i = 0; i < cnt; i ++ )
{
sp += p[ans[i]];
sd += d[ans[i]];
}
printf("Jury #%d\n", T ++ );
printf("Best jury has value %d for prosecution and value %d for defence:\n", sp, sd);
sort(ans, ans + cnt);
for (int i = 0; i < cnt; i ++ ) printf(" %d", ans[i]);
puts("\n");
}
return 0;
}
4.Coins
题目链接
题解:完全背包裸题,没什么好说的
java代码:
import java.util.Arrays;
import java.util.HashMap;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n,m;
int a[]=new int[105];
int c[]=new int[105];
int f[]=new int[100000+10];
int q[]=new int[100000+10];
int g[]=new int[100000+10];
while(true) {
n = sc.nextInt();
m = sc.nextInt();
if (n == 0 && m == 0)
break;
for (int i = 1; i <= n; i++) {
a[i] = sc.nextInt();
}
for (int i = 1; i <= n; i++) {
c[i] = sc.nextInt();
}
Arrays.fill(f,0);
Arrays.fill(q,0);
f[0]=1;
for(int i=1;i<=n;i++)
{
g=Arrays.copyOfRange(f,0,f.length-1);
for(int j=0;j<a[i];j++)
{
int hh=0,tt=-1;
for(int k=j;k<=m;k+=a[i])
{
f[k]=g[k];
if(hh<=tt && k-c[i]*a[i]>q[hh])
//如果当前窗口的内容超过了s个;
{
hh++;
}
if(hh<=tt)
{
f[k]=1;
//max(f[i-1][k],f[i-1][能转移里最大]+个数*v[i]);
}
if(g[k]>0)
q[++tt]=k;
}
}
}
int ans=0;
for(int i=1;i<=m;i++)
if(f[i]>0) ans++;
System.out.println(ans);
}
}
}
c++代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
const int M = 1e5 + 10;
int a[N],c[N];
int f[M],used[M];
int main()
{
ios::sync_with_stdio(false);
int n,m;
for ( ; ; )
{
int ans = 0;
cin >> n >> m;
if ( n == 0 && m == 0) break;
for (int i = 1; i <= n; ++ i ) cin >> a[i];
for (int i = 1; i <= n; ++ i ) cin >> c[i];
memset(f,0,sizeof(f));
memset(used,0,sizeof(used));
f[0] = 1;
for (int i = 1; i <= n; ++ i )
{
for (int j = 0; j <= m; ++ j ) used[j] = 0;
for (int j = a[i]; j <= m; ++ j )
{
if (!f[j] && used[j - a[i]] < c[i] && f[j - a[i]])
f[j] = true, used[j] = used[j - a[i]] + 1;
}
}
for (int i = 1; i <= m; ++ i )
if (f[i]) ++ans;
cout << ans << endl;
}
return 0;
}
有问题请留言或者私信,谢谢
扫描二维码关注公众号,回复:
12559045 查看本文章