P2066 机器分配 解析
Posted yemanlin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2066 机器分配 解析相关的知识,希望对你有一定的参考价值。
小日记:
1、今天新学的字体颜色,尽管不熟悉,但玩的666,卡星(开心)
╰( ̄▽ ̄)╮╰( ̄▽ ̄)╮╰( ̄▽ ̄)╮╰( ̄▽ ̄)╮╰( ̄▽ ̄)╮╰( ̄▽ ̄)╮
2、今天油腔滑调,谅解亿下
题目
总公司拥有高效设备\\(M\\)台,准备分给下属的\\(N\\)个分公司。各分公司若获得这些设备,可以为国家提供一定的盈利。问:如何分配这\\(M\\)台设备才能使国家得到的盈利最大?
求出最大盈利值。其中\\(M≤15,N≤10\\)。
分配原则:每个公司有权获得任意数目的设备,但总台数不超过设备数M。
输入
第一行有两个数,第一个数是分公司数\\(N\\),第二个数是设备台数M。
接下来是一个\\(N*M\\)的矩阵,表明了第 \\(I\\)个公司分配 \\(J\\)台机器的盈利。
输出
第1行为最大盈利值
第2到第n为第i分公司分x台
\\(P.S.\\) 要求答案的字典序最小(为后文埋下伏笔)
样例
解析
设\\(f[i][j]\\)为前\\(i\\)个公司总共分配\\(j\\)台机器的最大利润。对于第\\(i\\)家子公司,我们可以给其分配的机器台数为:\\(1-m\\)
所以在该区间内枚举一个值k,状态转移方程即为:
\\(f[i][j]=max(f[i-1][j-k],f[i][j])\\)
那么,如何处理方案输出问题呢?
我们设\\(path[i][j][h]\\)对于前i个公司共分配\\(j\\)台机器的最优方案,第\\(h\\)个公司应分配多少台机器,当状态发生转移时,更新\\(path\\)数组即可。最终的答案就存放在\\(path[n][m][i]\\)之中。
代码如下
#include <bits/stdc++.h>
using namespace std;
int a[25][25];
int f[25][25];
int path[25][25][25];
int n,m;
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
for (int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
}
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
for (int k=0;k<=j;k++){
if (f[i][j]<f[i-1][j-k]+a[i][k]){
f[i][j]=f[i-1][j-k]+a[i][k];
for (int l=1;l<i;l++)
path[i][j][l]=path[i-1][j-k][l];
path[i][j][i]=k;
}
}
printf("%d\\n",f[n][m]);
for (int i=1;i<=n;i++)printf("%d %d\\n",i,path[n][m][i]);
return 0;
}
巴特(But),you only have 90 分的好成绩
Why???
回到题面,我们会发现小小的一行字,人畜无害的鸭子(样子)
>(\' )
)/
/( <---鸭子
/ `----/
\\ ~=- /——:
要求答案的字典序最小
顿时,我***********
辣么,如何使字典序最小呢?这需要我们倒着枚举。
设方程式表示的意思为“不给”第i家公司k台机器(k的值域同上)
注意:并不是\\(f\\)的意思
那么状态转移方程需改为:
f[i][j]=max(f[i][k],f[i-1][k]+graph[i][j-k]);
再根据这个,对于path数组的更新操作进行一些微调,即可得到满分程序了:
#include <bits/stdc++.h>
using namespace std;
int a[25][25];
int f[25][25];
int path[25][25][25];
int n,m;
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
for (int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
}
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
for (int k=0;k<=j;k++){
if (f[i][j]<f[i-1][k]+a[i][j-k]){
f[i][j]=f[i-1][k]+a[i][j-k];
for (int l=1;l<i;l++)
path[i][j][l]=path[i-1][k][l];
path[i][j][i]=j-k;
}
}
printf("%d\\n",f[n][m]);
for (int i=1;i<=n;i++)printf("%d %d\\n",i,path[n][m][i]);
return 0;
}
机器学习P问题NP问题NP-hardNP-C问题解析与举例理解
1 基本概念
1.1 多项式和时间复杂度
(1)多项式
a
x
n
+
b
x
n
−
1
+
c
ax^n+bx^{n-1}+c
axn+bxn−1+c,形如这种形式的就被称为x的最高位为n的多项式。
(1)时间复杂度
定义为随着问题规模的增大,算法执行时间增长的快慢。它可以用来表示一个算法运行的时间效率。举个例子,冒泡排序的时间复杂度为
O
(
n
2
)
O(n^2)
O(n2) ,取其最高次,可以看出,这是一个时间复杂度为多项式的表示方式
1.2 P和NP
(1)P(deterministic polynomial time question):
多项式时间问题,简称P问题,意思是能在多项式时间内解决的问题。简单理解是算起来很快的问题
(2)NP(No-deterministic polynomial time question)
非确定多项式时间问题,简称NP问题,就是能在多项式时间验证答案正确与否的问题。简单的理解是NP问题算起来不一定快,但对于任何答案我们都可以快速的验证这个答案对不对。
1.3 NP-hard和NP-C
NP-hardness问题:任意NP问题都可以在多项式时间内归约为一类问题,这类问题就称为NP-hard问题,这是比所有的NP问题都难的问题。归约的意思是为了解决问题A,先将问题A归约为另一个问题B,解决问题B同时也间接解决了问题A。
NP-Complete问题:但若所有的NP问题都能多项式归约到一类问题X,则称X为NP-hard问题,进一步如果X是NP的,称X是NP complete的。换句话说,只要解决了这个问题,那么所有的NP问题都解决了。其定义要满足2个条件:一是NP-hard的问题,二是NP问题。
1.4 总结
(1)理想:NP问题 = P问题
NP=P意思是,如果对于一个问题能在多项式时间内验证其答案的正确性,那么是否能在多项式时间内解决它。
因为如果将所有的NP问题都多项式规约到某一个NP Complete问题,且只要一个NP Complete问题能在多项式时间内得到解决的话,那么所有的NP问题都可以在多项式时间内得到解决了。这个问题的解决将会带来世界性的进步。
(2)现实:我们仍然相信P问题!=NP问题
至今并没有人能证明某个NP Complete问题是P的。而且目前主流的观点是P不等于NP,当然这也没有确切的证明。如左图所示。
2 举例理解NP问题
最著名的NP问题是TSP旅行商推销问题。题目是在以下条件下,求出访问所有城市的最短路径
- 推销商有N个目的地城市
- 他需要访问所有城市一次,即不能重复
- 任意两座城市都是连接的,距离已知,即对应有权完全图
分析:
解决这个问题如果单纯的用枚举法来列举的话会有(n-1)! 种,已经不是多项式时间的算法了。将会是N的阶乘的复杂度O(n!)。
但是有快捷的方法,可以用猜的,假设人品爆炸猜几次就猜中了一条小于长度a的路径,TSP问题解决了,皆大欢喜。可是,我不可能每次都猜的那么准,也许我要猜完所有种方案呢?所以我们说,这是一个NP类问题。也就是这个问题能在多项式的时间内验证并得出问题的正确解,可是我们却不知道该问题是否存在一个多项式时间的算法,每次都能解决他(注意,这里是不知道,不是不存在,即能解决,但是无法找到一个多项式时间的算法的通解)
3 其他NP问题
- Edge Cover 边覆盖
- Set Cover 集合覆盖
- Steiner Tree(Forest) 斯坦纳树
- Max cut 最大割
- SAT 可满足性
以上是关于P2066 机器分配 解析的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向使用 Python 解析 ELF 文件 ( Capstone 反汇编 ELF 文件中的机器码数据 | 创建反汇编解析器实例对象 | 设置汇编解析器显示细节 )(代码片段