又看题解了,然后代码又没看懂、、
思路:任意挑数组合时:假设某个数是最多的,有maxx个,剩下的总共sum个。有4种情况。
1.maxx 大于 sum+1时,那么一定不成立,把剩下的数全插入最多的数的缝中也填不满,一定会有两个数相邻。所以该情况无法符合题意。
2.maxx 等于 sum+1时,那么只能将maxx的数两端都占有。假设有maxx个的数是x,其他的是o, 就只能 xoxoxoxox 这样排。
3.maxx 等于 sum 时,那么x只要占有一端就行,可以是:xoxoxoxoxo或者oxoxoxoxox。
4.maxx 小于 sum 时,那么就可以随意插了,只要插的时候不重复即可。
#include
using namespace std;
#define int long long
const int mod=1e9+7;
const int N=100;
int v[N];
bool dfs(vector &res)
{
int sum=0,maxx=0,ans=-1;
for(int i=0;i<10;i++)
{
if(v[i]>maxx) //找出最多的数
{
maxx=v[i];
ans=i;
}
sum+=v[i];
}
if(sum==0)return 1;
sum-=maxx;//剩下的数有多少个
if(maxx>sum+1)return false; //情况1
if(maxx==sum+1)//情况2,此时ans必须两端占
{
if(ans==0&&res.empty())//如果ans是数字0且res里还没存数字
{
return false;
}
else
{
res.push_back(ans);//???没看懂
v[ans]--;
}
}
else
{
int u= res.size()==0 ? 1:0;
int k= u==1 ? -1:res.back();
for(int i=u;i<10;i++)
{
if(v[i] && i!=k)
{
res.push_back(i);
v[i]--;
break;
}
}
}
return dfs(res);
}
signed main() {
int n=10;
int sum=0;
for(int i=0;i<10;i++)
{
cin>>v[i];
sum+=v[i];
}
if(v[0]==1&&sum==1)
{
cout<<"0"<res;
if(dfs(res))
{
if(res.size()==0)cout<<-1<
#include
using namespace std;
int main()
{
int n;
char a[105][105];
cin>>n;
for(int i=1;i<=(n+1)/2;i++)
{
int w=1;
for(int j=2;j<=i;j++)
{
if(j%2==0)
a[i][w++]='+';
else
a[i][w++]='.';
}
for(int k=1;k<=(n-2*(i-1));k++)
{
if(i%2==0)
a[i][w++]='.';
else
a[i][w++]='+';
}
for(int j=i;j>=2;j--)
{
if(j%2==0)
a[i][w++]='+';
else
a[i][w++]='.';
}
}
for(int i=1;i<=(n+1)/2;i++)
{
for(int j=1;j<=n;j++)
cout<=1;i--)
{
for(int j=n;j>=1;j--)
cout<
#386. 特殊的正方形
还没完全学会的dp题、、注释见下
#include
using namespace std;
long long dp[55][3];
//dp[i][j]表示的是上到第i级台阶,走了j次两级台阶
int main()
{
int n;
cin>>n;
dp[0][0]=1;
for(int i=0;i<=n;i++)
{
for(int j=0;j<3;j++)
{
if(j!=2)
dp[i+2][j+1]+=dp[i][j];
dp[i+1][0]+=dp[i][j];
}
}
cout<
走楼梯2 - 题目 - Daimayuan Online Judge
又是dp题…没看懂题解
#include
#define int long long
using namespace std;
const int N = 1e5 + 107;
bool f[103][N];
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
int n, m;
cin >> n >> m;
f[0][0] = true;
for (int i = 1; i <= n; i++) {
int a, b;
cin >> a >> b;
for (int j = m; j >= min(a,b); j--) {
f[i][j] |= f[i - 1][j - min(a,b)];
if (j >= max(a,b)) f[i][j] |= f[i - 1][j - max(a,b)];
}
}
for (int i = 0; i <= m; i++) {
if (f[n][i]) cout << "1";
else cout << "0";
}
}
走路 - 题目 - Daimayuan Online Judge
#include
using namespace std;
map pro;
map fri;
string peo[205];
int main()
{
int n,m,k;
cin>>n>>m>>k;
for(int i=0;i>peo[i];
for(int i=0;i>s>>x;
pro[s]=x;
}
for(int i=0;i>s1>>s2>>s3;
if(s3=="AC")
{
fri[s1]+=pro[s2];
}
}
for(int i=0;i
简单分数统计 - 题目 - Daimayuan Online Judge
#include
using namespace std;
char ans[8][20]={"ROYAL FLUSH","STRAIGHT FLUSH", "FOUR OF A KIND","FULL HOUSE","FLUSH","STRAIGHT","FOLD"};
int flag[8],a[6],b[6];
int f=1,f2=0;
int main()
{
for(int i=0;i<5;i++)
cin>>a[i];
for(int i=0;i<5;i++)
cin>>b[i];
for(int i=0;i<4;i++)
{
if(!(a[i]+1==a[i+1]&&b[i]==b[i+1]&&a[4]==14))
flag[0]=1;
if(!(a[i]+1==a[i+1]&&b[i]==b[i+1]))
flag[1]=1;
if(a[i]==a[i+1])
{
f2=max(f2,++f);
}
else
f=1;
if(b[i]!=b[i+1])
flag[4]=1;
if(a[i]+1!=a[i+1])
flag[5]=1;
}
if(f2<4)
flag[2]=1;
if(!(f2==3&&(a[0]==a[1]||a[3]==a[4])))
flag[3]=1;
for(int i=0;i<6;i++)
{
if(!flag[i])
{
cout<
Alice的德州扑克 - 题目 - Daimayuan Online Judge
new!并查集问题!
int findRoot(int x)
{
if(mp[x]!=x)
mp[x]=findRoot(mp[x]);
return mp[x];
}
合并
void unionTree(int a,int b)
{
int x=findRoot(a);
int y=findRoot(b);//在执行findRoot的时候就已经把b的值变成它的根的值了
if(x==y) return;
if(x>y) swap(x,y);//让大的还是让小的为根可以根据题目决定
mp[x]=y;
return ;
}
关于map
本题思路:把出现过的数字并在一堆,根为这一堆里最大的数字+1(即重复出现这堆数字中的数时应该取的数字),用ans存最后的答案输出即可
#include
using namespace std;
const int N=1e6+10;
int ans[N],a[N];
int n;
unordered_map mp;
int findRoot(int x)
{
if(mp[x]!=x)
mp[x]=findRoot(mp[x]);
return mp[x];
}
void unionTree(int a,int b)
{
int x=findRoot(a);
int y=findRoot(b);//在执行findRoot的时候就已经把b的值变成它的根的值了
if(x==y) return;
if(x>y) swap(x,y);//这题让大的为根
mp[x]=y;
return ;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
mp[a[i]]=a[i];
}
for(int i=1;i<=n;i++)
{
int now=a[i];
int root=findRoot(a[i]);
if(now==root) //如果这个数字还没被使用过
{
ans[i]=now;
if(mp.count(now+1)==0) mp[now+1]=now+1;//如果比这个数字大一的数字还没有使用过
unionTree(now,now+1);//并进去作为这个的根
}
else //如果这个数字已经使用过
{
ans[i]= root;
if(mp.count(root+1)==0) mp[root+1]=root+1;
unionTree(root,root+1);
}
}
for(int i=1;i<=n;i++)
cout<
订单编号 - 题目 - Daimayuan Online Judge
二分答案题
思路:二分法,check轮数x,找到最后一轮的情况,然后模拟一下队列
注意:
最后一个测试点超时了,很崩溃,试着用map存了一次删除出队的数据,but失败了,##肝不动了我选择摆烂
#include
using namespace std;
const long long N=1e5+10;
long long n,k,ans=-2,sum=0;
long long a[N];
long long check(int x)
{
long long s=0; //s表示的是x轮吃掉的饭的数量
for(long long i=1;i<=n;i++)
{
if(a[i]=0) return (k-s); //返回阿姨还应该打的饭的数量
else return -1;
}
int main()
{
cin>>n>>k;
for(long long i=1;i<=n;i++)
{
cin>>a[i];
sum+=a[i];
}
if(sum
饿饿 饭饭 - 题目 - Daimayuan Online Judge
状态转移方程依然没看懂、、这周必把dp刷会
#include
#define ll long long
using namespace std;
int dp[1004];
struct node {
int l,r,w;
}ms[1004];
bool cmp(node a,node b){
if(a.r == b.r) return a.l > b.l;
return a.r < b.r;
}
int main(){
int n;
cin >> n;
for(int i = 1; i <= n; i++){
cin >> ms[i].l >> ms[i].r >> ms[i].w;
}
sort(ms + 1,ms + 1 + n,cmp);
for(int i = 1; i <= n; i++){
for(int j = 1; j <= ms[i].l; j++){
dp[j] = max(dp[j],dp[j - 1]);
if(j == ms[i].l){
dp[ms[i].r] = max(dp[ms[i].l] + ms[i].w,dp[ms[i].r]);
}
}
}
int maxn = 0;
for(int j = 1; j <= 1000; j++){
maxn = max(dp[j],maxn);
}
cout << maxn << '\n';
return 0;
}
任务分配 - 题目 - Daimayuan Online Judge
#include
using namespace std;
int dp[1005][1005];//dp[i][j]表示以第i行第j列为终点的最大值
int a[1005][1005];
int ma;
int main()
{
int r;
cin>>r;
for(int i=1;i<=r;i++)
{
for(int j=1;j<=i;j++)
{
cin>>a[i][j];
}
dp[i][1]=a[i][1]+dp[i-1][1];
}
for(int i=2;i<=r;i++)
{
for(int j=2;j<=i;j++)
{
dp[i][j]=max(dp[i-1][j-1],dp[i-1][j])+a[i][j];
if(i==r)
{
ma=max(dp[i][j],ma);
}
}
}
cout<
dp[1]=a[1][1];
for(int i=2;i<=r;i++)
{
for(int j=i;j>=2;j--) //从后往前,不然会被覆盖
{
dp[j]=max(dp[j-1],dp[j])+a[i][j];
if(i==r)
{
ma=max(dp[j],ma);
}
}
dp[1]+=a[i][1]; //更新dp[1]
}
#include
using namespace std;
int a[25],dp[25],path[25][25],p[25];
//dp[i]表示以i为终点地雷最多的路
//p[i]表示最优路径下i的前驱 后续输出路径
int n,maxn,maxi;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
dp[i]=a[i];//初始化
}
for(int i=1;i>path[i][j]; //表示i能否通向j
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;jmaxn)
{
// cout< s;
while(maxi)
{
s.push(maxi);
maxi=p[maxi];
}
cout<
01背包问题
#include
using namespace std;
const int N=30010;
int w[N],v[N],dp[N];
int m,n;
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
cin>>v[i]>>w[i];
for(int i=1;i<=m;i++)
{
for(int j=n;j>=1;j--)
{
if(j>=v[i])
dp[j]=max(dp[j],dp[j-v[i]]+v[i]*w[i]);
}
}
cout<
感觉不太对劲,题目说用dp但是我很简单就过掉了(?
#include
using namespace std;
string s1,s2;
int ans,len1,len2;
int main()
{
cin>>s1>>s2;
len1=s1.length();
len2=s2.length();
for(int i=0;i
#include
using namespace std;
int m,n;
int dp[35][35];//到第i行第j列有多少条路
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
dp[1][i]=1;
for(int i=1;i<=n;i++)
dp[i][1]=1;
for(int i=2;i<=n;i++)
{
for(int j=2;j<=m;j++)
{
if(i%2!=0||j%2!=0)
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
cout<
#include
using namespace std;
int n,x;
long long lose[1010],win[1010],use[1010],dp[1010][1010];
int main()
{
cin>>n>>x;
for(int i=1;i<=n;i++)
{
cin>>lose[i]>>win[i]>>use[i];
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<=x;j++)
{
if(j>=use[i])
dp[i][j]=max(dp[i-1][j],dp[i-1][j-use[i]]+win[i]);
dp[i][j]=max(dp[i][j],dp[i-1][j]+lose[i]);
}
}
cout<<5*dp[n][x]<
#include
using namespace std;
int r,c,ans;
int mp[105][105],dp[105][105];//dp[i][j]表示从i j出发的最长道路是多少
int xx[5]={0,1,0,-1};
int yy[5]={-1,0,1,0};
int dfs(int x,int y)
{
if(dp[x][y]) return dp[x][y];//记忆化搜索
dp[x][y]=1;
for(int i=0;i<4;i++)
{
int nx=x+xx[i];
int ny=y+yy[i];
if(nx>=1&&nx<=r&&ny>=1&&ny<=c&&mp[x][y]>mp[nx][ny])
{
dfs(nx,ny);
dp[x][y]=max(dp[x][y],dp[nx][ny]+1);
}
}
return dp[x][y];
}
int main()
{
cin>>r>>c;
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
cin>>mp[i][j];
}
}
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
ans=max(ans,dfs(i,j));
}
}
cout<